diff options
37 files changed, 606 insertions, 242 deletions
@@ -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() } } @@ -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; +}; |