summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--src/codegen/impl_debug.rs (renamed from src/codegen/derive_debug.rs)0
-rw-r--r--src/codegen/mod.rs50
-rw-r--r--src/ir/analysis/derive_copy.rs9
-rw-r--r--src/ir/analysis/derive_debug.rs8
-rw-r--r--src/ir/analysis/derive_default.rs8
-rw-r--r--src/ir/analysis/derive_hash.rs8
-rw-r--r--src/ir/analysis/derive_partial_eq_or_partial_ord.rs101
-rw-r--r--src/ir/comp.rs39
-rw-r--r--src/ir/context.rs48
-rw-r--r--src/ir/derive.rs118
-rw-r--r--src/ir/function.rs54
-rw-r--r--src/ir/item.rs12
-rw-r--r--src/ir/layout.rs29
-rw-r--r--src/lib.rs70
-rw-r--r--src/options.rs24
-rw-r--r--tests/expectations/tests/bitfield_large_overflow.rs21
-rw-r--r--tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs2
-rw-r--r--tests/expectations/tests/derive-hash-struct-with-float-array.rs2
-rw-r--r--tests/expectations/tests/derive-hash-struct-with-pointer.rs10
-rw-r--r--tests/expectations/tests/derive-hash-template-def-float.rs2
-rw-r--r--tests/expectations/tests/derive-hash-template-inst-float.rs10
-rw-r--r--tests/expectations/tests/no-partialeq-opaque.rs29
-rw-r--r--tests/expectations/tests/no-partialeq-whitelisted.rs39
-rw-r--r--tests/expectations/tests/underscore.rs40
-rw-r--r--tests/expectations/tests/whitelisted-item-references-no-partialeq.rs62
-rw-r--r--tests/headers/bitfield_large_overflow.hpp5
-rw-r--r--tests/headers/derive-hash-blacklisting.hpp2
-rw-r--r--tests/headers/derive-hash-struct-with-anon-struct-float.h4
-rw-r--r--tests/headers/derive-hash-struct-with-float-array.h4
-rw-r--r--tests/headers/derive-hash-struct-with-pointer.h4
-rw-r--r--tests/headers/derive-hash-template-def-float.hpp4
-rw-r--r--tests/headers/derive-hash-template-inst-float.hpp8
-rw-r--r--tests/headers/no-partialeq-opaque.hpp5
-rw-r--r--tests/headers/no-partialeq-whitelisted.hpp5
-rw-r--r--tests/headers/underscore.hpp3
-rw-r--r--tests/headers/whitelisted-item-references-no-partialeq.hpp7
37 files changed, 606 insertions, 242 deletions
diff --git a/README.md b/README.md
index 1dd3259b..4a233a98 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# `bindgen`
+[`impl period`](https://blog.rust-lang.org/2017/09/18/impl-future-for-rust.html) has been started! Join us at [Gitter.im](https://gitter.im/rust-impl-period/WG-dev-tools-bindgen).
+
**`bindgen` automatically generates Rust FFI bindings to C and C++ libraries.**
For example, given the C header `doggo.h`:
diff --git a/src/codegen/derive_debug.rs b/src/codegen/impl_debug.rs
index 7ef108da..7ef108da 100644
--- a/src/codegen/derive_debug.rs
+++ b/src/codegen/impl_debug.rs
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 810f1367..0da01175 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1,4 +1,4 @@
-mod derive_debug;
+mod impl_debug;
mod error;
mod helpers;
pub mod struct_layout;
@@ -12,8 +12,8 @@ use ir::comp::{Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field,
FieldData, FieldMethods, Method, MethodKind};
use ir::context::{BindgenContext, ItemId};
use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault,
- CanDeriveHash, CanDerivePartialOrd, CanDerivePartialEq,
- CanDeriveEq};
+ CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd,
+ CanDerivePartialEq, CanDeriveEq};
use ir::dot;
use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
use ir::function::{Abi, Function, FunctionSig};
@@ -865,24 +865,6 @@ impl CodeGenerator for TemplateInstantiation {
}
}
-/// Generates an infinite number of anonymous field names.
-struct AnonFieldNames(usize);
-
-impl Default for AnonFieldNames {
- fn default() -> AnonFieldNames {
- AnonFieldNames(0)
- }
-}
-
-impl Iterator for AnonFieldNames {
- type Item = String;
-
- fn next(&mut self) -> Option<String> {
- self.0 += 1;
- Some(format!("__bindgen_anon_{}", self.0))
- }
-}
-
/// Trait for implementing the code generation of a struct or union field.
trait FieldCodegen<'a> {
type Extra;
@@ -894,7 +876,6 @@ trait FieldCodegen<'a> {
codegen_depth: usize,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
- anon_field_names: &mut AnonFieldNames,
result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
@@ -915,7 +896,6 @@ impl<'a> FieldCodegen<'a> for Field {
codegen_depth: usize,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
- anon_field_names: &mut AnonFieldNames,
result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
@@ -933,7 +913,6 @@ impl<'a> FieldCodegen<'a> for Field {
codegen_depth,
accessor_kind,
parent,
- anon_field_names,
result,
struct_layout,
fields,
@@ -948,7 +927,6 @@ impl<'a> FieldCodegen<'a> for Field {
codegen_depth,
accessor_kind,
parent,
- anon_field_names,
result,
struct_layout,
fields,
@@ -970,7 +948,6 @@ impl<'a> FieldCodegen<'a> for FieldData {
codegen_depth: usize,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
- anon_field_names: &mut AnonFieldNames,
result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
@@ -1030,7 +1007,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
let field_name =
self.name()
.map(|name| ctx.rust_mangle(name).into_owned())
- .unwrap_or_else(|| anon_field_names.next().unwrap());
+ .expect("Each field should have a name in codegen!");
let field_ident = ctx.rust_ident_raw(field_name.as_str());
if !parent.is_union() {
@@ -1164,7 +1141,6 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
codegen_depth: usize,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
- anon_field_names: &mut AnonFieldNames,
result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
@@ -1213,7 +1189,6 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
codegen_depth,
accessor_kind,
parent,
- anon_field_names,
result,
struct_layout,
fields,
@@ -1321,7 +1296,6 @@ impl<'a> FieldCodegen<'a> for Bitfield {
_codegen_depth: usize,
_accessor_kind: FieldAccessorKind,
parent: &CompInfo,
- _anon_field_names: &mut AnonFieldNames,
_result: &mut CodegenResult,
_struct_layout: &mut StructLayoutTracker,
_fields: &mut F,
@@ -1494,6 +1468,10 @@ impl CodeGenerator for CompInfo {
derives.push("PartialOrd");
}
+ if item.can_derive_ord(ctx) {
+ derives.push("Ord");
+ }
+
if item.can_derive_partialeq(ctx) {
derives.push("PartialEq");
}
@@ -1555,7 +1533,7 @@ impl CodeGenerator for CompInfo {
struct_layout.saw_vtable();
}
- for (i, base) in self.base_members().iter().enumerate() {
+ for base in self.base_members() {
// Virtual bases are already taken into account by the vtable
// pointer.
//
@@ -1573,11 +1551,7 @@ impl CodeGenerator for CompInfo {
}
let inner = base.ty.to_rust_ty_or_opaque(ctx, &());
- let field_name = ctx.rust_ident(if i == 0 {
- "_base".into()
- } else {
- format!("_base_{}", i)
- });
+ let field_name = ctx.rust_ident(&base.field_name);
struct_layout.saw_base(base_ty);
@@ -1595,7 +1569,6 @@ impl CodeGenerator for CompInfo {
let mut methods = vec![];
if !is_opaque {
- let mut anon_field_names = AnonFieldNames::default();
let codegen_depth = item.codegen_depth(ctx);
let fields_should_be_private =
item.annotations().private_fields().unwrap_or(false);
@@ -1609,7 +1582,6 @@ impl CodeGenerator for CompInfo {
codegen_depth,
struct_accessor_kind,
self,
- &mut anon_field_names,
result,
&mut struct_layout,
&mut fields,
@@ -1910,7 +1882,7 @@ impl CodeGenerator for CompInfo {
}
if needs_debug_impl {
- let impl_ = derive_debug::gen_debug_impl(
+ let impl_ = impl_debug::gen_debug_impl(
ctx,
self.fields(),
item,
diff --git a/src/ir/analysis/derive_copy.rs b/src/ir/analysis/derive_copy.rs
index ef01c65a..264d227a 100644
--- a/src/ir/analysis/derive_copy.rs
+++ b/src/ir/analysis/derive_copy.rs
@@ -9,6 +9,7 @@ use ir::derive::CanTriviallyDeriveCopy;
use ir::item::IsOpaque;
use ir::template::TemplateParameters;
use ir::traversal::EdgeKind;
+use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
use ir::ty::TypeKind;
use std::collections::HashMap;
use std::collections::HashSet;
@@ -266,6 +267,14 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
self.is_not_copy(data.ty())
}
Field::Bitfields(ref bfu) => {
+ if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT {
+ trace!(
+ " we cannot derive Copy for a bitfield larger then \
+ the limit"
+ );
+ return true;
+ }
+
bfu.bitfields().iter().any(|b| {
self.is_not_copy(b.ty())
})
diff --git a/src/ir/analysis/derive_debug.rs b/src/ir/analysis/derive_debug.rs
index 2bfaff71..7df745c9 100644
--- a/src/ir/analysis/derive_debug.rs
+++ b/src/ir/analysis/derive_debug.rs
@@ -268,6 +268,14 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
self.is_not_debug(data.ty())
}
Field::Bitfields(ref bfu) => {
+ if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT {
+ trace!(
+ " we cannot derive Debug for a bitfield larger then \
+ the limit"
+ );
+ return true;
+ }
+
bfu.bitfields().iter().any(|b| {
self.is_not_debug(b.ty())
})
diff --git a/src/ir/analysis/derive_default.rs b/src/ir/analysis/derive_default.rs
index 96805863..7acbe04a 100644
--- a/src/ir/analysis/derive_default.rs
+++ b/src/ir/analysis/derive_default.rs
@@ -308,6 +308,14 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
self.is_not_default(data.ty())
}
Field::Bitfields(ref bfu) => {
+ if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT {
+ trace!(
+ " we cannot derive Default for a bitfield larger then \
+ the limit"
+ );
+ return true;
+ }
+
bfu.bitfields().iter().any(|b| {
!self.ctx.whitelisted_items().contains(
&b.ty(),
diff --git a/src/ir/analysis/derive_hash.rs b/src/ir/analysis/derive_hash.rs
index 80ea0abf..5313cae3 100644
--- a/src/ir/analysis/derive_hash.rs
+++ b/src/ir/analysis/derive_hash.rs
@@ -283,6 +283,14 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
self.cannot_derive_hash.contains(&data.ty())
}
Field::Bitfields(ref bfu) => {
+ if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT {
+ trace!(
+ " we cannot derive Hash for a bitfield larger then \
+ the limit"
+ );
+ return true;
+ }
+
bfu.bitfields().iter().any(|b| {
!self.ctx.whitelisted_items().contains(
&b.ty(),
diff --git a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs
index 876477ab..f34a256a 100644
--- a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs
+++ b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs
@@ -1,4 +1,5 @@
-//! Determining which types for which we can emit `#[derive(PartialEq)]`.
+//! Determining which types for which we cannot emit `#[derive(PartialEq,
+//! PartialOrd)]`.
use super::{ConstrainResult, MonotoneFramework, generate_dependencies};
use ir::comp::CompKind;
@@ -13,31 +14,39 @@ use ir::ty::TypeKind;
use std::collections::HashMap;
use std::collections::HashSet;
-/// An analysis that finds for each IR item whether partialeq or partialord cannot be derived.
+/// An analysis that finds for each IR item whether `PartialEq`/`PartialOrd`
+/// cannot be derived.
///
-/// We use the monotone constraint function `cannot_derive_partialeq_or_partialord`, defined as
-/// follows:
+/// We use the monotone constraint function
+/// `cannot_derive_partialeq_or_partialord`, defined as follows:
///
/// * If T is Opaque and layout of the type is known, get this layout as opaque
/// type and check whether it can be derived using trivial checks.
-/// * If T is Array type, partialeq or partialord cannot be derived if the length of
-/// the array is larger than the limit or the type of data the array contains cannot derive
-/// partialeq or partialord.
+///
+/// * If T is Array type, `PartialEq` or partialord cannot be derived if the
+/// length of the array is larger than the limit or the type of data the array
+/// contains cannot derive `PartialEq`/`PartialOrd`.
+///
/// * If T is a type alias, a templated alias or an indirection to another type,
-/// partialeq or partialord cannot be derived if the type T refers to cannot be derived partialeq or partialord.
-/// * If T is a compound type, partialeq or partialord cannot be derived if any of its base member
-/// or field cannot be derived partialeq or partialord.
-/// * If T is a pointer, T cannot be derived partialeq or partialord if T is a function pointer
-/// and the function signature cannot be derived partialeq or partialord.
+/// `PartialEq`/`PartialOrd` cannot be derived if the type T refers to cannot be
+/// derived `PartialEq`/`PartialOrd`.
+///
+/// * If T is a compound type, `PartialEq`/`PartialOrd` cannot be derived if any
+/// of its base member or field cannot be derived `PartialEq`/`PartialOrd`.
+///
+/// * If T is a pointer, T cannot be derived `PartialEq`/`PartialOrd` if T is a
+/// function pointer and the function signature cannot be derived
+/// `PartialEq`/`PartialOrd`.
+///
/// * If T is an instantiation of an abstract template definition, T cannot be
-/// derived partialeq or partialord if any of the template arguments or template definition
-/// cannot derive partialeq or partialord.
+/// derived `PartialEq`/`PartialOrd` if any of the template arguments or
+/// template definition cannot derive `PartialEq`/`PartialOrd`.
#[derive(Debug, Clone)]
pub struct CannotDerivePartialEqOrPartialOrd<'ctx> {
ctx: &'ctx BindgenContext,
// The incremental result of this analysis's computation. Everything in this
- // set cannot derive partialeq or partialord.
+ // set cannot derive `PartialEq`/`PartialOrd`.
cannot_derive_partialeq_or_partialord: HashSet<ItemId>,
// Dependencies saying that if a key ItemId has been inserted into the
@@ -46,7 +55,7 @@ pub struct CannotDerivePartialEqOrPartialOrd<'ctx> {
//
// This is a subset of the natural IR graph with reversed edges, where we
// only include the edges from the IR graph that can affect whether a type
- // can derive partialeq or partialord.
+ // can derive `PartialEq`/`PartialOrd`.
dependencies: HashMap<ItemId, Vec<ItemId>>,
}
@@ -54,7 +63,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
fn consider_edge(kind: EdgeKind) -> bool {
match kind {
// These are the only edges that can affect whether a type can derive
- // partialeq or partialord.
+ // `PartialEq`/`PartialOrd`.
EdgeKind::BaseMember |
EdgeKind::Field |
EdgeKind::TypeReference |
@@ -115,7 +124,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
trace!("constrain: {:?}", id);
if self.cannot_derive_partialeq_or_partialord.contains(&id) {
- trace!(" already know it cannot derive PartialEq or PartialOrd");
+ trace!(" already know it cannot derive `PartialEq`/`PartialOrd`");
return ConstrainResult::Same;
}
@@ -128,6 +137,10 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
}
};
+ if self.ctx.no_partialeq_by_name(&item) {
+ return self.insert(id)
+ }
+
trace!("ty: {:?}", ty);
if item.is_opaque(self.ctx, &()) {
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
@@ -136,10 +149,10 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
return if layout_can_derive &&
!(ty.is_union() &&
self.ctx.options().rust_features().untagged_union()) {
- trace!(" we can trivially derive PartialEq or PartialOrd for the layout");
+ trace!(" we can trivially derive `PartialEq`/`PartialOrd` for the layout");
ConstrainResult::Same
} else {
- trace!(" we cannot derive PartialEq or PartialOrd for the layout");
+ trace!(" we cannot derive `PartialEq`/`PartialOrd` for the layout");
self.insert(id)
};
}
@@ -172,24 +185,24 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
TypeKind::ObjCInterface(..) |
TypeKind::ObjCId |
TypeKind::ObjCSel => {
- trace!(" simple type that can always derive PartialEq or PartialOrd");
+ trace!(" simple type that can always derive `PartialEq`/`PartialOrd`");
ConstrainResult::Same
}
TypeKind::Array(t, len) => {
if self.cannot_derive_partialeq_or_partialord.contains(&t) {
trace!(
- " arrays of T for which we cannot derive PartialEq or PartialOrd \
- also cannot derive PartialEq or PartialOrd"
+ " arrays of T for which we cannot derive `PartialEq`/`PartialOrd` \
+ also cannot derive `PartialEq`/`PartialOrd`"
);
return self.insert(id);
}
if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
- trace!(" array is small enough to derive PartialEq or PartialOrd");
+ trace!(" array is small enough to derive `PartialEq`/`PartialOrd`");
ConstrainResult::Same
} else {
- trace!(" array is too large to derive PartialEq or PartialOrd");
+ trace!(" array is too large to derive `PartialEq`/`PartialOrd`");
self.insert(id)
}
}
@@ -200,7 +213,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
if let TypeKind::Function(ref sig) = *inner_type.kind() {
if !sig.can_trivially_derive_partialeq_or_partialord() {
trace!(
- " function pointer that can't trivially derive PartialEq or PartialOrd"
+ " function pointer that can't trivially derive `PartialEq`/`PartialOrd`"
);
return self.insert(id);
}
@@ -212,11 +225,11 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
TypeKind::Function(ref sig) => {
if !sig.can_trivially_derive_partialeq_or_partialord() {
trace!(
- " function that can't trivially derive PartialEq or PartialOrd"
+ " function that can't trivially derive `PartialEq`/`PartialOrd`"
);
return self.insert(id);
}
- trace!(" function can derive PartialEq or PartialOrd");
+ trace!(" function can derive `PartialEq`/`PartialOrd`");
ConstrainResult::Same
}
@@ -226,13 +239,13 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
if self.cannot_derive_partialeq_or_partialord.contains(&t) {
trace!(
" aliases and type refs to T which cannot derive \
- PartialEq or PartialOrd also cannot derive PartialEq or PartialOrd"
+ `PartialEq`/`PartialOrd` also cannot derive `PartialEq`/`PartialOrd`"
);
self.insert(id)
} else {
trace!(
" aliases and type refs to T which can derive \
- PartialEq or PartialOrd can also derive PartialEq or PartialOrd"
+ `PartialEq`/`PartialOrd` can also derive `PartialEq`/`PartialOrd`"
);
ConstrainResult::Same
}
@@ -246,7 +259,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
if info.kind() == CompKind::Union {
if self.ctx.options().rust_features().untagged_union() {
- trace!(" cannot derive PartialEq or PartialOrd for Rust unions");
+ trace!(" cannot derive `PartialEq`/`PartialOrd` for Rust unions");
return self.insert(id);
}
@@ -255,11 +268,11 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
})
{
trace!(
- " union layout can trivially derive PartialEq or PartialOrd"
+ " union layout can trivially derive `PartialEq`/`PartialOrd`"
);
return ConstrainResult::Same;
} else {
- trace!(" union layout cannot derive PartialEq or PartialOrd");
+ trace!(" union layout cannot derive `PartialEq`/`PartialOrd`");
return self.insert(id);
}
}
@@ -271,7 +284,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
});
if bases_cannot_derive {
trace!(
- " base members cannot derive PartialEq or PartialOrd, so we can't \
+ " base members cannot derive `PartialEq`/`PartialOrd`, so we can't \
either"
);
return self.insert(id);
@@ -288,6 +301,14 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
)
}
Field::Bitfields(ref bfu) => {
+ if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT {
+ trace!(
+ " we cannot derive PartialEq for a bitfield larger then \
+ the limit"
+ );
+ return true;
+ }
+
bfu.bitfields().iter().any(|b| {
!self.ctx.whitelisted_items().contains(
&b.ty(),
@@ -300,7 +321,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
});
if fields_cannot_derive {
trace!(
- " fields cannot derive PartialEq or PartialOrd, so we can't either"
+ " fields cannot derive `PartialEq`/`PartialOrd`, so we can't either"
);
return self.insert(id);
}
@@ -316,8 +337,8 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
});
if args_cannot_derive {
trace!(
- " template args cannot derive PartialEq or PartialOrd, so \
- insantiation can't either"
+ " template args cannot derive `PartialEq`/`PartialOrd`, so \
+ insantiation can't either"
);
return self.insert(id);
}
@@ -331,13 +352,13 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
);
if def_cannot_derive {
trace!(
- " template definition cannot derive PartialEq or PartialOrd, so \
- insantiation can't either"
+ " template definition cannot derive `PartialEq`/`PartialOrd`, so \
+ insantiation can't either"
);
return self.insert(id);
}
- trace!(" template instantiation can derive PartialEq or PartialOrd");
+ trace!(" template instantiation can derive `PartialEq`/`PartialOrd`");
ConstrainResult::Same
}
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index bbccd06a..fc17ab8f 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -666,6 +666,33 @@ impl CompFields {
CompFields::AfterComputingBitfieldUnits(fields_and_units),
);
}
+
+ fn deanonymize_fields(&mut self) {
+ let fields = match *self {
+ CompFields::AfterComputingBitfieldUnits(ref mut fields) => {
+ fields
+ }
+ CompFields::BeforeComputingBitfieldUnits(_) => {
+ panic!("Not yet computed bitfield units.");
+ }
+ };
+
+ let mut anon_field_counter = 0;
+ for field in fields.iter_mut() {
+ let field_data = match *field {
+ Field::DataMember(ref mut fd) => fd,
+ Field::Bitfields(_) => continue,
+ };
+
+ if let Some(_) = field_data.name {
+ continue;
+ }
+
+ anon_field_counter += 1;
+ let name = format!("__bindgen_anon_{}", anon_field_counter);
+ field_data.name = Some(name);
+ }
+ }
}
impl Trace for CompFields {
@@ -769,6 +796,8 @@ pub struct Base {
pub ty: ItemId,
/// The kind of inheritance we're doing.
pub kind: BaseKind,
+ /// Name of the field in which this base should be stored.
+ pub field_name: String,
}
impl Base {
@@ -1155,11 +1184,16 @@ impl CompInfo {
BaseKind::Normal
};
+ let field_name = match ci.base_members.len() {
+ 0 => "_base".into(),
+ n => format!("_base_{}", n),
+ };
let type_id =
Item::from_ty_or_ref(cur.cur_type(), cur, None, ctx);
ci.base_members.push(Base {
ty: type_id,
kind: kind,
+ field_name: field_name,
});
}
CXCursor_Constructor |
@@ -1344,6 +1378,11 @@ impl CompInfo {
self.fields.compute_bitfield_units(ctx);
}
+ /// Assign for each anonymous field a generated name.
+ pub fn deanonymize_fields(&mut self) {
+ self.fields.deanonymize_fields();
+ }
+
/// Returns whether the current union can be represented as a Rust `union`
///
/// Requirements:
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 513cc665..b540d152 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -6,8 +6,8 @@ use super::analysis::{CannotDeriveCopy, CannotDeriveDebug,
HasVtableAnalysis, HasDestructorAnalysis, UsedTemplateParameters,
HasFloat, analyze};
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault,
- CanDeriveHash, CanDerivePartialOrd, CanDerivePartialEq,
- CanDeriveEq};
+ CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd,
+ CanDerivePartialEq, CanDeriveEq};
use super::int::IntKind;
use super::item::{HasTypeParamInArray, IsOpaque, Item, ItemAncestors,
ItemCanonicalPath, ItemSet};
@@ -91,6 +91,14 @@ impl CanDeriveEq for ItemId {
}
}
+impl CanDeriveOrd for ItemId {
+ fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
+ ctx.options().derive_ord &&
+ ctx.lookup_item_id_can_derive_partialeq_or_partialord(*self) &&
+ !ctx.lookup_item_id_has_float(&self)
+ }
+}
+
/// A key used to index a resolved type, so we only process it once.
///
/// This is almost always a USR string (an unique identifier generated by
@@ -231,8 +239,9 @@ pub struct BindgenContext {
/// The set of (`ItemId`s of) types that can't derive hash.
///
- /// This is populated when we enter codegen by `compute_can_derive_partialeq`
- /// and is always `None` before that and `Some` after.
+ /// This is populated when we enter codegen by
+ /// `compute_cannot_derive_partialord_partialeq_or_eq` and is always `None`
+ /// before that and `Some` after.
cannot_derive_partialeq_or_partialord: Option<HashSet<ItemId>>,
/// The set of (`ItemId's of`) types that has vtable.
@@ -672,7 +681,8 @@ impl BindgenContext {
"where" |
"while" |
"yield" |
- "bool" => true,
+ "bool" |
+ "_" => true,
_ => false,
}
{
@@ -790,6 +800,18 @@ impl BindgenContext {
}
}
+ /// Assign a new generated name for each anonymous field.
+ fn deanonymize_fields(&mut self) {
+ let _t = self.timer("deanonymize_fields");
+ let comp_types = self.items
+ .values_mut()
+ .filter_map(|item| item.kind_mut().as_type_mut())
+ .filter_map(Type::as_comp_mut);
+ for comp_info in comp_types {
+ comp_info.deanonymize_fields();
+ }
+ }
+
/// Iterate over all items and replace any item that has been named in a
/// `replaces="SomeType"` annotation with the replacement type.
fn process_replacements(&mut self) {
@@ -931,6 +953,8 @@ impl BindgenContext {
self.compute_bitfield_units();
self.process_replacements();
}
+
+ self.deanonymize_fields();
// And assert once again, because resolving type refs and processing
// replacements both mutate the IR graph.
@@ -2140,8 +2164,7 @@ impl BindgenContext {
}
}
- /// Look up whether the item with `id` can
- /// derive partialeq or partialord.
+ /// Look up whether the item with `id` can derive `Partial{Eq,Ord}`.
pub fn lookup_item_id_can_derive_partialeq_or_partialord(&self, id: ItemId) -> bool {
assert!(
self.in_codegen_phase(),
@@ -2153,8 +2176,7 @@ impl BindgenContext {
!self.cannot_derive_partialeq_or_partialord.as_ref().unwrap().contains(&id)
}
- /// Look up whether the item with `id` can
- /// derive copy or not.
+ /// Look up whether the item with `id` can derive `Copy` or not.
pub fn lookup_item_id_can_derive_copy(&self, id: ItemId) -> bool {
assert!(
self.in_codegen_phase(),
@@ -2191,7 +2213,7 @@ impl BindgenContext {
fn compute_has_float(&mut self) {
let _t = self.timer("compute_has_float");
assert!(self.has_float.is_none());
- if self.options.derive_eq {
+ if self.options.derive_eq || self.options.derive_ord {
self.has_float = Some(analyze::<HasFloat>(self));
}
}
@@ -2205,6 +2227,12 @@ impl BindgenContext {
// float or not.
self.has_float.as_ref().unwrap().contains(id)
}
+
+ /// Check if `--no-partialeq` flag is enabled for this item.
+ pub fn no_partialeq_by_name(&self, item: &Item) -> bool {
+ let name = item.canonical_path(self)[1..].join("::");
+ self.options().no_partialeq_types.matches(&name)
+ }
}
/// A builder struct for configuring item resolution options.
diff --git a/src/ir/derive.rs b/src/ir/derive.rs
index 0d6b2875..cafbd3b1 100644
--- a/src/ir/derive.rs
+++ b/src/ir/derive.rs
@@ -1,27 +1,32 @@
//! Traits for determining whether we can derive traits for a thing or not.
+//!
+//! These traits tend to come in pairs:
+//!
+//! 1. A "trivial" version, whose implementations aren't allowed to recursively
+//! look at other types or the results of fix point analyses.
+//!
+//! 2. A "normal" version, whose implementations simply query the results of a
+//! fix point analysis.
+//!
+//! The former is used by the analyses when creating the results queried by the
+//! second.
use super::context::BindgenContext;
/// A trait that encapsulates the logic for whether or not we can derive `Debug`
/// for a given thing.
-///
-/// This should ideally be a no-op that just returns `true`, but instead needs
-/// to be a recursive method that checks whether all the proper members can
-/// derive debug or not, because of the limit rust has on 32 items as max in the
-/// array.
pub trait CanDeriveDebug {
/// Return `true` if `Debug` can be derived for this thing, `false`
/// otherwise.
fn can_derive_debug(&self, ctx: &BindgenContext) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `Debug`.
-/// The difference between this trait and the CanDeriveDebug is that the type
-/// implementing this trait cannot use recursion or lookup result from fix point
-/// analysis. It's a helper trait for fix point analysis.
+/// A trait that encapsulates the logic for whether or not we can trivially
+/// derive `Debug` without looking at any other types or the results of a fix
+/// point analysis. This is a helper trait for the fix point analysis.
pub trait CanTriviallyDeriveDebug {
- /// Return `true` if `Debug` can be derived for this thing, `false`
- /// otherwise.
+ /// Return `true` if `Debug` can trivially be derived for this thing,
+ /// `false` otherwise.
fn can_trivially_derive_debug(&self) -> bool;
}
@@ -33,72 +38,50 @@ pub trait CanDeriveCopy<'a> {
fn can_derive_copy(&'a self, ctx: &'a BindgenContext) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `Copy`.
-/// The difference between this trait and the CanDeriveCopy is that the type
-/// implementing this trait cannot use recursion or lookup result from fix point
-/// analysis. It's a helper trait for fix point analysis.
+/// A trait that encapsulates the logic for whether or not we can trivially
+/// derive `Copy` without looking at any other types or results of fix point
+/// analsyses. This is a helper trait for fix point analysis.
pub trait CanTriviallyDeriveCopy {
- /// Return `true` if `Copy` can be derived for this thing, `false`
+ /// Return `true` if `Copy` can be trivially derived for this thing, `false`
/// otherwise.
fn can_trivially_derive_copy(&self) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `Default`
-/// for a given thing.
-///
-/// This should ideally be a no-op that just returns `true`, but instead needs
-/// to be a recursive method that checks whether all the proper members can
-/// derive default or not, because of the limit rust has on 32 items as max in the
-/// array.
+/// A trait that encapsulates the logic for whether or not we can derive
+/// `Default` for a given thing.
pub trait CanDeriveDefault {
/// Return `true` if `Default` can be derived for this thing, `false`
/// otherwise.
fn can_derive_default(&self, ctx: &BindgenContext) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `Default`.
-/// The difference between this trait and the CanDeriveDefault is that the type
-/// implementing this trait cannot use recursion or lookup result from fix point
-/// analysis. It's a helper trait for fix point analysis.
+/// A trait that encapsulates the logic for whether or not we can trivially
+/// derive `Default` without looking at any other types or results of fix point
+/// analyses. This is a helper trait for the fix point analysis.
pub trait CanTriviallyDeriveDefault {
- /// Return `true` if `Default` can be derived for this thing, `false`
+ /// Return `true` if `Default` can trivially derived for this thing, `false`
/// otherwise.
fn can_trivially_derive_default(&self) -> bool;
}
/// A trait that encapsulates the logic for whether or not we can derive `Hash`
/// for a given thing.
-///
-/// This should ideally be a no-op that just returns `true`, but instead needs
-/// to be a recursive method that checks whether all the proper members can
-/// derive default or not, because of the limit rust has on 32 items as max in the
-/// array.
pub trait CanDeriveHash {
- /// Return `true` if `Default` can be derived for this thing, `false`
+ /// Return `true` if `Hash` can be derived for this thing, `false`
/// otherwise.
fn can_derive_hash(&self, ctx: &BindgenContext) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `PartialEq`
-/// for a given thing.
-///
-/// This should ideally be a no-op that just returns `true`, but instead needs
-/// to be a recursive method that checks whether all the proper members can
-/// derive default or not, because of the limit rust has on 32 items as max in the
-/// array.
+/// A trait that encapsulates the logic for whether or not we can derive
+/// `PartialEq` for a given thing.
pub trait CanDerivePartialEq {
/// Return `true` if `PartialEq` can be derived for this thing, `false`
/// otherwise.
fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `PartialOrd`
-/// for a given thing.
-///
-/// This should ideally be a no-op that just returns `true`, but instead needs
-/// to be a recursive method that checks whether all the proper members can
-/// derive default or not, because of the limit rust has on 32 items as max in the
-/// array.
+/// A trait that encapsulates the logic for whether or not we can derive
+/// `PartialOrd` for a given thing.
pub trait CanDerivePartialOrd {
/// Return `true` if `PartialOrd` can be derived for this thing, `false`
/// otherwise.
@@ -107,37 +90,32 @@ pub trait CanDerivePartialOrd {
/// A trait that encapsulates the logic for whether or not we can derive `Eq`
/// for a given thing.
-///
-/// This should ideally be a no-op that just returns `true`, but instead needs
-/// to be a recursive method that checks whether all the proper members can
-/// derive eq or not, because of the limit rust has on 32 items as max in the
-/// array.
pub trait CanDeriveEq {
+ /// Return `true` if `Eq` can be derived for this thing, `false` otherwise.
+ fn can_derive_eq(&self, ctx: &BindgenContext) -> bool;
+}
- /// Return `true` if `Eq` can be derived for this thing, `false`
- /// otherwise.
- fn can_derive_eq(&self,
- ctx: &BindgenContext)
- -> bool;
+/// A trait that encapsulates the logic for whether or not we can derive `Ord`
+/// for a given thing.
+pub trait CanDeriveOrd {
+ /// Return `true` if `Ord` can be derived for this thing, `false` otherwise.
+ fn can_derive_ord(&self, ctx: &BindgenContext) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `Hash`.
-/// The difference between this trait and the CanDeriveHash is that the type
-/// implementing this trait cannot use recursion or lookup result from fix point
-/// analysis. It's a helper trait for fix point analysis.
+/// A trait that encapsulates the logic for whether or not we can derive `Hash`
+/// without looking at any other types or the results of any fix point
+/// analyses. This is a helper trait for the fix point analysis.
pub trait CanTriviallyDeriveHash {
- /// Return `true` if `Hash` can be derived for this thing, `false`
+ /// Return `true` if `Hash` can trivially be derived for this thing, `false`
/// otherwise.
fn can_trivially_derive_hash(&self) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `PartialEq`
-/// or `PartialOrd`.
-/// The difference between this trait and the CanDerivePartialEq is that the type
-/// implementing this trait cannot use recursion or lookup result from fix point
-/// analysis. It's a helper trait for fix point analysis.
+/// A trait that encapsulates the logic for whether or not we can trivially
+/// derive `PartialEq` or `PartialOrd` without looking at any other types or
+/// results of fix point analyses. This is a helper for the fix point analysis.
pub trait CanTriviallyDerivePartialEqOrPartialOrd {
- /// Return `true` if `PartialEq` or `PartialOrd` can be derived for this thing, `false`
- /// otherwise.
+ /// Return `true` if `PartialEq` or `PartialOrd` can trivially be derived
+ /// for this thing, `false` otherwise.
fn can_trivially_derive_partialeq_or_partialord(&self) -> bool;
}
diff --git a/src/ir/function.rs b/src/ir/function.rs
index f37f0f3c..402a0230 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -437,6 +437,26 @@ impl FunctionSig {
// variadic functions without an initial argument.
self.is_variadic && !self.argument_types.is_empty()
}
+
+ /// Are function pointers with this signature able to derive Rust traits?
+ /// Rust only supports deriving traits for function pointers with a limited
+ /// number of parameters and a couple ABIs.
+ ///
+ /// For more details, see:
+ ///
+ /// * https://github.com/rust-lang-nursery/rust-bindgen/issues/547,
+ /// * https://github.com/rust-lang/rust/issues/38848,
+ /// * and https://github.com/rust-lang/rust/issues/40158
+ pub fn function_pointers_can_derive(&self) -> bool {
+ if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
+ return false;
+ }
+
+ match self.abi {
+ Abi::C | Abi::Unknown(..) => true,
+ _ => false,
+ }
+ }
}
impl ClangSubItemParser for Function {
@@ -523,48 +543,20 @@ impl Trace for FunctionSig {
}
}
-// Function pointers follow special rules, see:
-//
-// https://github.com/rust-lang-nursery/rust-bindgen/issues/547,
-// https://github.com/rust-lang/rust/issues/38848,
-// and https://github.com/rust-lang/rust/issues/40158
-//
-// Note that copy is always derived, so we don't need to implement it.
impl CanTriviallyDeriveDebug for FunctionSig {
fn can_trivially_derive_debug(&self) -> bool {
- if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
- return false;
- }
-
- match self.abi {
- Abi::C | Abi::Unknown(..) => true,
- _ => false,
- }
+ self.function_pointers_can_derive()
}
}
impl CanTriviallyDeriveHash for FunctionSig {
fn can_trivially_derive_hash(&self) -> bool {
- if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
- return false;
- }
-
- match self.abi {
- Abi::C | Abi::Unknown(..) => true,
- _ => false,
- }
+ self.function_pointers_can_derive()
}
}
impl CanTriviallyDerivePartialEqOrPartialOrd for FunctionSig {
fn can_trivially_derive_partialeq_or_partialord(&self) -> bool {
- if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
- return false;
- }
-
- match self.abi {
- Abi::C | Abi::Unknown(..) => true,
- _ => false,
- }
+ self.function_pointers_can_derive()
}
}
diff --git a/src/ir/item.rs b/src/ir/item.rs
index dbc215cf..8a5a143b 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -6,8 +6,8 @@ use super::comment;
use super::comp::MethodKind;
use super::context::{BindgenContext, ItemId, PartialType};
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault,
- CanDeriveHash, CanDerivePartialOrd, CanDerivePartialEq,
- CanDeriveEq};
+ CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd,
+ CanDerivePartialEq, CanDeriveEq};
use super::dot::DotAttributes;
use super::function::{Function, FunctionKind};
use super::item_kind::ItemKind;
@@ -353,6 +353,14 @@ impl CanDeriveEq for Item {
}
}
+impl CanDeriveOrd for Item {
+ fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
+ ctx.options().derive_ord &&
+ ctx.lookup_item_id_can_derive_partialeq_or_partialord(self.id()) &&
+ !ctx.lookup_item_id_has_float(&self.id())
+ }
+}
+
/// An item is the base of the bindgen representation, it can be either a
/// module, a type, a function, or a variable (see `ItemKind` for more
/// information).
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
index 298fe54a..2df15ef2 100644
--- a/src/ir/layout.rs
+++ b/src/ir/layout.rs
@@ -104,44 +104,43 @@ impl Opaque {
None
}
}
-}
-impl CanTriviallyDeriveDebug for Opaque {
- fn can_trivially_derive_debug(&self) -> bool {
+ /// Return `true` if this opaque layout's array size will fit within the
+ /// maximum number of array elements that Rust allows deriving traits
+ /// with. Return `false` otherwise.
+ pub fn array_size_within_derive_limit(&self) -> bool {
self.array_size().map_or(false, |size| {
size <= RUST_DERIVE_IN_ARRAY_LIMIT
})
}
}
+impl CanTriviallyDeriveDebug for Opaque {
+ fn can_trivially_derive_debug(&self) -> bool {
+ self.array_size_within_derive_limit()
+ }
+}
+
impl CanTriviallyDeriveDefault for Opaque {
fn can_trivially_derive_default(&self) -> bool {
- self.array_size().map_or(false, |size| {
- size <= RUST_DERIVE_IN_ARRAY_LIMIT
- })
+ self.array_size_within_derive_limit()
}
}
impl CanTriviallyDeriveCopy for Opaque {
fn can_trivially_derive_copy(&self) -> bool {
- self.array_size().map_or(false, |size| {
- size <= RUST_DERIVE_IN_ARRAY_LIMIT
- })
+ self.array_size_within_derive_limit()
}
}
impl CanTriviallyDeriveHash for Opaque {
fn can_trivially_derive_hash(&self) -> bool {
- self.array_size().map_or(false, |size| {
- size <= RUST_DERIVE_IN_ARRAY_LIMIT
- })
+ self.array_size_within_derive_limit()
}
}
impl CanTriviallyDerivePartialEqOrPartialOrd for Opaque {
fn can_trivially_derive_partialeq_or_partialord(&self) -> bool {
- self.array_size().map_or(false, |size| {
- size <= RUST_DERIVE_IN_ARRAY_LIMIT
- })
+ self.array_size_within_derive_limit()
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 72770411..dbb9c268 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -247,7 +247,7 @@ impl Builder {
output_vector.push("--no-derive-debug".into());
}
- if !self.options.impl_debug {
+ if self.options.impl_debug {
output_vector.push("--impl-debug".into());
}
@@ -265,6 +265,10 @@ impl Builder {
output_vector.push("--with-derive-partialord".into());
}
+ if self.options.derive_ord {
+ output_vector.push("--with-derive-ord".into());
+ }
+
if self.options.derive_partialeq {
output_vector.push("--with-derive-partialeq".into());
}
@@ -500,6 +504,20 @@ impl Builder {
output_vector.push(path.into());
}
+ self.options
+ .no_partialeq_types
+ .get_items()
+ .iter()
+ .map(|item| {
+ output_vector.push("--no-partialeq".into());
+ output_vector.push(
+ item.trim_left_matches("^")
+ .trim_right_matches("$")
+ .into(),
+ );
+ })
+ .count();
+
output_vector
}
@@ -819,14 +837,29 @@ impl Builder {
}
/// Set whether `PartialOrd` should be derived by default.
+ /// If we don't compute partialord, we also cannot compute
+ /// ord. Set the derive_ord to `false` when doit is `false`.
pub fn derive_partialord(mut self, doit: bool) -> Self {
self.options.derive_partialord = doit;
+ if !doit {
+ self.options.derive_ord = false;
+ }
+ self
+ }
+
+ /// Set whether `Ord` should be derived by default.
+ /// We can't compute `Ord` without computing `PartialOrd`,
+ /// so we set the same option to derive_partialord.
+ pub fn derive_ord(mut self, doit: bool) -> Self {
+ self.options.derive_ord = doit;
+ self.options.derive_partialord = doit;
self
}
/// Set whether `PartialEq` should be derived by default.
- /// If we don't compute partialeq, we also cannot compute
- /// eq. Set the derive_eq to `false` when doit is `false`.
+ ///
+ /// If we don't derive `PartialEq`, we also cannot derive `Eq`, so deriving
+ /// `Eq` is also disabled when `doit` is `false`.
pub fn derive_partialeq(mut self, doit: bool) -> Self {
self.options.derive_partialeq = doit;
if !doit {
@@ -836,16 +869,19 @@ impl Builder {
}
/// Set whether `Eq` should be derived by default.
- /// We can't compute Eq without computing PartialEq, so
- /// we set the same option to derive_partialeq.
+ ///
+ /// We can't derive `Eq` without also deriving `PartialEq`, so we also
+ /// enable deriving `PartialEq` when `doit` is `true`.
pub fn derive_eq(mut self, doit: bool) -> Self {
self.options.derive_eq = doit;
- self.options.derive_partialeq = doit;
+ if doit {
+ self.options.derive_partialeq = doit;
+ }
self
}
- /// Set whether or not to time bindgen phases, and print
- /// information to stderr.
+ /// Set whether or not to time bindgen phases, and print information to
+ /// stderr.
pub fn time_phases(mut self, doit: bool) -> Self {
self.options.time_phases = doit;
self
@@ -1105,6 +1141,13 @@ impl Builder {
))
}
}
+
+ /// Don't derive `PartialEq` for a given type. Regular
+ /// expressions are supported.
+ pub fn no_partialeq(mut self, arg: String) -> Builder {
+ self.options.no_partialeq_types.insert(arg);
+ self
+ }
}
/// Configuration options for generated bindings.
@@ -1190,6 +1233,10 @@ struct BindgenOptions {
/// and types.
derive_partialord: bool,
+ /// True if we should derive Ord trait implementations for C/C++ structures
+ /// and types.
+ derive_ord: bool,
+
/// True if we should derive PartialEq trait implementations for C/C++ structures
/// and types.
derive_partialeq: bool,
@@ -1279,7 +1326,11 @@ struct BindgenOptions {
/// The absolute path to the rustfmt configuration file, if None, the standard rustfmt
/// options are used.
+
rustfmt_configuration_file: Option<PathBuf>,
+
+ /// The set of types that we should not derive `PartialEq` for.
+ no_partialeq_types: RegexSet,
}
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -1297,6 +1348,7 @@ impl BindgenOptions {
self.bitfield_enums.build();
self.constified_enum_modules.build();
self.rustified_enums.build();
+ self.no_partialeq_types.build();
}
/// Update rust target version
@@ -1340,6 +1392,7 @@ impl Default for BindgenOptions {
derive_default: false,
derive_hash: false,
derive_partialord: false,
+ derive_ord: false,
derive_partialeq: false,
derive_eq: false,
enable_cxx_namespaces: false,
@@ -1365,6 +1418,7 @@ impl Default for BindgenOptions {
time_phases: false,
rustfmt_bindings: false,
rustfmt_configuration_file: None,
+ no_partialeq_types: Default::default(),
}
}
}
diff --git a/src/options.rs b/src/options.rs
index b3182270..d8a98641 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -88,7 +88,12 @@ where
.help("Derive partialord on any type."),
Arg::with_name("with-derive-eq")
.long("with-derive-eq")
- .help("Derive eq on any type. Enable this option also enables --with-derive-partialeq"),
+ .help("Derive eq on any type. Enable this option also \
+ enables --with-derive-partialeq"),
+ Arg::with_name("with-derive-ord")
+ .long("with-derive-ord")
+ .help("Derive ord on any type. Enable this option also \
+ enables --with-derive-partialord"),
Arg::with_name("no-doc-comments")
.long("no-doc-comments")
.help("Avoid including doc comments in the output, see: \
@@ -265,6 +270,13 @@ where
.takes_value(true)
.multiple(false)
.number_of_values(1),
+ Arg::with_name("no-partialeq")
+ .long("no-partialeq")
+ .help("Avoid deriving PartialEq for types matching <regex>.")
+ .value_name("regex")
+ .takes_value(true)
+ .multiple(true)
+ .number_of_values(1),
]) // .args()
.get_matches_from(args);
@@ -351,6 +363,10 @@ where
builder = builder.derive_eq(true);
}
+ if matches.is_present("with-derive-ord") {
+ builder = builder.derive_ord(true);
+ }
+
if matches.is_present("no-derive-default") {
builder = builder.derive_default(false);
}
@@ -537,6 +553,12 @@ where
builder = builder.rustfmt_configuration_file(Some(path));
}
+ if let Some(no_partialeq) = matches.values_of("no-partialeq") {
+ for regex in no_partialeq {
+ builder = builder.no_partialeq(String::from(regex));
+ }
+ }
+
let verbose = matches.is_present("verbose");
Ok((builder, output, verbose))
diff --git a/tests/expectations/tests/bitfield_large_overflow.rs b/tests/expectations/tests/bitfield_large_overflow.rs
new file mode 100644
index 00000000..523570e4
--- /dev/null
+++ b/tests/expectations/tests/bitfield_large_overflow.rs
@@ -0,0 +1,21 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+#[repr(C)]
+pub struct _bindgen_ty_1 {
+ pub _bitfield_1: [u8; 128usize],
+ pub __bindgen_align: [u64; 0usize],
+}
+impl Default for _bindgen_ty_1 {
+ fn default() -> Self {
+ unsafe { ::std::mem::zeroed() }
+ }
+}
+extern "C" {
+ #[link_name = "a"]
+ pub static mut a: _bindgen_ty_1;
+}
+
diff --git a/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs b/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs
index da1d2b41..6436b69a 100644
--- a/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs
+++ b/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs
@@ -5,7 +5,7 @@
-/// A struct containing a struct containing a float that cannot derive hash/eq but can derive partialeq and partialord
+/// A struct containing a struct containing a float that cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd
#[repr(C)]
#[derive(Debug, Default, Copy, PartialOrd, PartialEq)]
pub struct foo {
diff --git a/tests/expectations/tests/derive-hash-struct-with-float-array.rs b/tests/expectations/tests/derive-hash-struct-with-float-array.rs
index a14a0829..dd9acc6a 100644
--- a/tests/expectations/tests/derive-hash-struct-with-float-array.rs
+++ b/tests/expectations/tests/derive-hash-struct-with-float-array.rs
@@ -5,7 +5,7 @@
-/// A struct containing an array of floats that cannot derive hash/eq but can derive partialeq and partialord
+/// A struct containing an array of floats that cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd
#[repr(C)]
#[derive(Debug, Default, Copy, PartialOrd, PartialEq)]
pub struct foo {
diff --git a/tests/expectations/tests/derive-hash-struct-with-pointer.rs b/tests/expectations/tests/derive-hash-struct-with-pointer.rs
index 664a19da..b2ae7ab2 100644
--- a/tests/expectations/tests/derive-hash-struct-with-pointer.rs
+++ b/tests/expectations/tests/derive-hash-struct-with-pointer.rs
@@ -5,9 +5,9 @@
-/// Pointers can derive Hash/PartialOrd/PartialEq/Eq
+/// Pointers can derive Hash/PartialOrd/Ord/PartialEq/Eq
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct ConstPtrMutObj {
pub bar: *const ::std::os::raw::c_int,
}
@@ -45,7 +45,7 @@ impl Default for ConstPtrMutObj {
}
}
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct MutPtrMutObj {
pub bar: *mut ::std::os::raw::c_int,
}
@@ -83,7 +83,7 @@ impl Default for MutPtrMutObj {
}
}
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct MutPtrConstObj {
pub bar: *const ::std::os::raw::c_int,
}
@@ -121,7 +121,7 @@ impl Default for MutPtrConstObj {
}
}
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct ConstPtrConstObj {
pub bar: *const ::std::os::raw::c_int,
}
diff --git a/tests/expectations/tests/derive-hash-template-def-float.rs b/tests/expectations/tests/derive-hash-template-def-float.rs
index d882f99d..853d77af 100644
--- a/tests/expectations/tests/derive-hash-template-def-float.rs
+++ b/tests/expectations/tests/derive-hash-template-def-float.rs
@@ -5,7 +5,7 @@
-/// Template definition containing a float, which cannot derive hash/eq but can derive partialeq and partialord.
+/// Template definition containing a float, which cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd.
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub struct foo<T> {
diff --git a/tests/expectations/tests/derive-hash-template-inst-float.rs b/tests/expectations/tests/derive-hash-template-inst-float.rs
index 7f79af3e..6473beba 100644
--- a/tests/expectations/tests/derive-hash-template-inst-float.rs
+++ b/tests/expectations/tests/derive-hash-template-inst-float.rs
@@ -5,9 +5,9 @@
-/// Template definition that doesn't contain float can derive hash/partialord/partialeq/eq
+/// Template definition that doesn't contain float can derive Hash/PartialOrd/Ord/PartialEq/Eq
#[repr(C)]
-#[derive(Debug, Copy, Clone, Hash, PartialOrd, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct foo<T> {
pub data: T,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
@@ -17,9 +17,9 @@ impl<T> Default for foo<T> {
unsafe { ::std::mem::zeroed() }
}
}
-/// Can derive hash/partialeq/eq when instantiated with int
+/// Can derive Hash/PartialOrd/Ord/PartialEq/Eq when instantiated with int
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct IntStr {
pub a: foo<::std::os::raw::c_int>,
}
@@ -56,7 +56,7 @@ impl Default for IntStr {
unsafe { ::std::mem::zeroed() }
}
}
-/// Cannot derive hash/eq when instantiated with float but can derive partialeq
+/// Cannot derive Hash/Eq/Ord when instantiated with float but can derive PartialEq/PartialOrd
#[repr(C)]
#[derive(Debug, Copy, PartialOrd, PartialEq)]
pub struct FloatStr {
diff --git a/tests/expectations/tests/no-partialeq-opaque.rs b/tests/expectations/tests/no-partialeq-opaque.rs
new file mode 100644
index 00000000..8fd5451f
--- /dev/null
+++ b/tests/expectations/tests/no-partialeq-opaque.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)]
+#[derive(Debug, Default, Copy)]
+pub struct NoPartialEq {
+ pub _bindgen_opaque_blob: u32,
+}
+#[test]
+fn bindgen_test_layout_NoPartialEq() {
+ assert_eq!(
+ ::std::mem::size_of::<NoPartialEq>(),
+ 4usize,
+ concat!("Size of: ", stringify!(NoPartialEq))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<NoPartialEq>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(NoPartialEq))
+ );
+}
+impl Clone for NoPartialEq {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
diff --git a/tests/expectations/tests/no-partialeq-whitelisted.rs b/tests/expectations/tests/no-partialeq-whitelisted.rs
new file mode 100644
index 00000000..f07864ce
--- /dev/null
+++ b/tests/expectations/tests/no-partialeq-whitelisted.rs
@@ -0,0 +1,39 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct NoPartialEq {
+ pub i: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_NoPartialEq() {
+ assert_eq!(
+ ::std::mem::size_of::<NoPartialEq>(),
+ 4usize,
+ concat!("Size of: ", stringify!(NoPartialEq))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<NoPartialEq>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(NoPartialEq))
+ );
+ assert_eq!(
+ unsafe { &(*(0 as *const NoPartialEq)).i as *const _ as usize },
+ 0usize,
+ concat!(
+ "Alignment of field: ",
+ stringify!(NoPartialEq),
+ "::",
+ stringify!(i)
+ )
+ );
+}
+impl Clone for NoPartialEq {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
diff --git a/tests/expectations/tests/underscore.rs b/tests/expectations/tests/underscore.rs
new file mode 100644
index 00000000..d1b0ccc2
--- /dev/null
+++ b/tests/expectations/tests/underscore.rs
@@ -0,0 +1,40 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+pub const __: ::std::os::raw::c_int = 10;
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct ptr_t {
+ pub __: [::std::os::raw::c_uchar; 8usize],
+}
+#[test]
+fn bindgen_test_layout_ptr_t() {
+ assert_eq!(
+ ::std::mem::size_of::<ptr_t>(),
+ 8usize,
+ concat!("Size of: ", stringify!(ptr_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<ptr_t>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(ptr_t))
+ );
+ assert_eq!(
+ unsafe { &(*(0 as *const ptr_t)).__ as *const _ as usize },
+ 0usize,
+ concat!(
+ "Alignment of field: ",
+ stringify!(ptr_t),
+ "::",
+ stringify!(__)
+ )
+ );
+}
+impl Clone for ptr_t {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
diff --git a/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs b/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs
new file mode 100644
index 00000000..a7bbab74
--- /dev/null
+++ b/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs
@@ -0,0 +1,62 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct NoPartialEq {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_NoPartialEq() {
+ assert_eq!(
+ ::std::mem::size_of::<NoPartialEq>(),
+ 1usize,
+ concat!("Size of: ", stringify!(NoPartialEq))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<NoPartialEq>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(NoPartialEq))
+ );
+}
+impl Clone for NoPartialEq {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct WhitelistMe {
+ pub a: NoPartialEq,
+}
+#[test]
+fn bindgen_test_layout_WhitelistMe() {
+ assert_eq!(
+ ::std::mem::size_of::<WhitelistMe>(),
+ 1usize,
+ concat!("Size of: ", stringify!(WhitelistMe))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<WhitelistMe>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(WhitelistMe))
+ );
+ assert_eq!(
+ unsafe { &(*(0 as *const WhitelistMe)).a as *const _ as usize },
+ 0usize,
+ concat!(
+ "Alignment of field: ",
+ stringify!(WhitelistMe),
+ "::",
+ stringify!(a)
+ )
+ );
+}
+impl Clone for WhitelistMe {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
diff --git a/tests/headers/bitfield_large_overflow.hpp b/tests/headers/bitfield_large_overflow.hpp
new file mode 100644
index 00000000..227829b8
--- /dev/null
+++ b/tests/headers/bitfield_large_overflow.hpp
@@ -0,0 +1,5 @@
+// bindgen-flags: --no-layout-tests
+
+struct {
+ unsigned : 632;
+} a;
diff --git a/tests/headers/derive-hash-blacklisting.hpp b/tests/headers/derive-hash-blacklisting.hpp
index 94a9f783..e3256a01 100644
--- a/tests/headers/derive-hash-blacklisting.hpp
+++ b/tests/headers/derive-hash-blacklisting.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq --whitelist-type 'Whitelisted.*' --blacklist-type Blacklisted --raw-line "#[repr(C)] #[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] pub struct Blacklisted<T> {t: T, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>> }"
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-ord --with-derive-partialeq --with-derive-eq --whitelist-type 'Whitelisted.*' --blacklist-type Blacklisted --raw-line "#[repr(C)] #[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] pub struct Blacklisted<T> {t: T, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>> }"
//
template <class T>
struct Blacklisted {
diff --git a/tests/headers/derive-hash-struct-with-anon-struct-float.h b/tests/headers/derive-hash-struct-with-anon-struct-float.h
index f96b9449..dc6e7329 100644
--- a/tests/headers/derive-hash-struct-with-anon-struct-float.h
+++ b/tests/headers/derive-hash-struct-with-anon-struct-float.h
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-ord --with-derive-partialeq --with-derive-eq
//
-/// A struct containing a struct containing a float that cannot derive hash/eq but can derive partialeq and partialord
+/// A struct containing a struct containing a float that cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd
struct foo {
struct {
float a;
diff --git a/tests/headers/derive-hash-struct-with-float-array.h b/tests/headers/derive-hash-struct-with-float-array.h
index 937217a0..2294b1de 100644
--- a/tests/headers/derive-hash-struct-with-float-array.h
+++ b/tests/headers/derive-hash-struct-with-float-array.h
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-ord --with-derive-partialeq --with-derive-eq
//
-/// A struct containing an array of floats that cannot derive hash/eq but can derive partialeq and partialord
+/// A struct containing an array of floats that cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd
struct foo {
float bar[3];
};
diff --git a/tests/headers/derive-hash-struct-with-pointer.h b/tests/headers/derive-hash-struct-with-pointer.h
index 9c8ba0f9..a3ce9cc5 100644
--- a/tests/headers/derive-hash-struct-with-pointer.h
+++ b/tests/headers/derive-hash-struct-with-pointer.h
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-ord --with-derive-partialeq --with-derive-eq
//
-/// Pointers can derive Hash/PartialOrd/PartialEq/Eq
+/// Pointers can derive Hash/PartialOrd/Ord/PartialEq/Eq
struct ConstPtrMutObj {
int* const bar;
};
diff --git a/tests/headers/derive-hash-template-def-float.hpp b/tests/headers/derive-hash-template-def-float.hpp
index 2dbe5409..253fb9ce 100644
--- a/tests/headers/derive-hash-template-def-float.hpp
+++ b/tests/headers/derive-hash-template-def-float.hpp
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-ord --with-derive-partialeq --with-derive-eq
//
-/// Template definition containing a float, which cannot derive hash/eq but can derive partialeq and partialord.
+/// Template definition containing a float, which cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd.
template <typename T>
struct foo {
T data;
diff --git a/tests/headers/derive-hash-template-inst-float.hpp b/tests/headers/derive-hash-template-inst-float.hpp
index d189ba71..0a4fc0c1 100644
--- a/tests/headers/derive-hash-template-inst-float.hpp
+++ b/tests/headers/derive-hash-template-inst-float.hpp
@@ -1,17 +1,17 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-ord --with-derive-partialeq --with-derive-eq
//
-/// Template definition that doesn't contain float can derive hash/partialord/partialeq/eq
+/// Template definition that doesn't contain float can derive Hash/PartialOrd/Ord/PartialEq/Eq
template <typename T>
struct foo {
T data;
};
-/// Can derive hash/partialeq/eq when instantiated with int
+/// Can derive Hash/PartialOrd/Ord/PartialEq/Eq when instantiated with int
struct IntStr {
foo<int> a;
};
-/// Cannot derive hash/eq when instantiated with float but can derive partialeq
+/// Cannot derive Hash/Eq/Ord when instantiated with float but can derive PartialEq/PartialOrd
struct FloatStr {
foo<float> a;
};
diff --git a/tests/headers/no-partialeq-opaque.hpp b/tests/headers/no-partialeq-opaque.hpp
new file mode 100644
index 00000000..a5a03cd2
--- /dev/null
+++ b/tests/headers/no-partialeq-opaque.hpp
@@ -0,0 +1,5 @@
+// bindgen-flags: --with-derive-partialeq --opaque-type "NoPartialEq" --no-partialeq "NoPartialEq"
+
+class NoPartialEq {
+ int i;
+};
diff --git a/tests/headers/no-partialeq-whitelisted.hpp b/tests/headers/no-partialeq-whitelisted.hpp
new file mode 100644
index 00000000..dba4e91f
--- /dev/null
+++ b/tests/headers/no-partialeq-whitelisted.hpp
@@ -0,0 +1,5 @@
+// bindgen-flags: --with-derive-partialeq --whitelist-type "NoPartialEq" --no-partialeq "NoPartialEq"
+
+class NoPartialEq {
+ int i;
+};
diff --git a/tests/headers/underscore.hpp b/tests/headers/underscore.hpp
new file mode 100644
index 00000000..1c9371f1
--- /dev/null
+++ b/tests/headers/underscore.hpp
@@ -0,0 +1,3 @@
+const int _ = 10;
+
+typedef struct { unsigned char _[8]; } ptr_t; \ No newline at end of file
diff --git a/tests/headers/whitelisted-item-references-no-partialeq.hpp b/tests/headers/whitelisted-item-references-no-partialeq.hpp
new file mode 100644
index 00000000..d9d3d431
--- /dev/null
+++ b/tests/headers/whitelisted-item-references-no-partialeq.hpp
@@ -0,0 +1,7 @@
+// bindgen-flags: --with-derive-partialeq --whitelist-type "WhitelistMe" --no-partialeq "NoPartialEq"
+
+struct NoPartialEq {};
+
+class WhitelistMe {
+ NoPartialEq a;
+};