diff options
-rw-r--r-- | src/codegen/mod.rs | 59 | ||||
-rw-r--r-- | tests/expectations/tests/bitfield-method-same-name.rs | 67 | ||||
-rw-r--r-- | tests/headers/bitfield-method-same-name.hpp | 6 |
3 files changed, 127 insertions, 5 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index c69116f9..7db083e7 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -753,6 +753,7 @@ impl<'a> Bitfield<'a> { fn codegen_fields(self, ctx: &BindgenContext, + parent: &CompInfo, fields: &mut Vec<ast::StructField>, methods: &mut Vec<ast::ImplItem>) -> Layout { @@ -790,6 +791,7 @@ impl<'a> Bitfield<'a> { // We've finished a physical field, so flush it and its bitfields. field_size_in_bits = align_to(field_size_in_bits, field_align); fields.push(flush_bitfields(ctx, + parent, field_size_in_bits, last_field_align, &last_field_name, @@ -831,6 +833,7 @@ impl<'a> Bitfield<'a> { if field_size_in_bits != 0 { // Flush the last physical field and its bitfields. fields.push(flush_bitfields(ctx, + parent, field_size_in_bits, last_field_align, &last_field_name, @@ -842,12 +845,59 @@ impl<'a> Bitfield<'a> { } } +fn parent_has_method(ctx: &BindgenContext, + parent: &CompInfo, + name: &str) + -> bool { + parent.methods().iter().any(|method| { + let method_name = match *ctx.resolve_item(method.signature()).kind() { + ItemKind::Function(ref func) => func.name(), + ref otherwise => panic!("a method's signature should always be a \ + item of kind ItemKind::Function, found: \ + {:?}", + otherwise), + }; + + method_name == name || ctx.rust_mangle(&method_name) == name + }) +} + +fn bitfield_getter_name(ctx: &BindgenContext, + parent: &CompInfo, + bitfield_name: &str) + -> ast::Ident { + let name = ctx.rust_mangle(bitfield_name); + + if parent_has_method(ctx, parent, &name) { + let mut name = name.to_string(); + name.push_str("_bindgen_bitfield"); + return ctx.ext_cx().ident_of(&name); + } + + ctx.ext_cx().ident_of(&name) +} + +fn bitfield_setter_name(ctx: &BindgenContext, + parent: &CompInfo, + bitfield_name: &str) + -> ast::Ident { + let setter = format!("set_{}", bitfield_name); + let mut setter = ctx.rust_mangle(&setter).to_string(); + + if parent_has_method(ctx, parent, &setter) { + setter.push_str("_bindgen_bitfield"); + } + + ctx.ext_cx().ident_of(&setter) +} + /// A physical field (which is a word or byte or ...) has many logical bitfields /// contained within it, but not all bitfields are in the same physical field of /// a struct. This function creates a single physical field and flushes all the /// accessors for the logical `bitfields` within that physical field to the /// outgoing `methods`. fn flush_bitfields<'a, I>(ctx: &BindgenContext, + parent: &CompInfo, field_size_in_bits: usize, field_align: usize, field_name: &str, @@ -867,9 +917,8 @@ fn flush_bitfields<'a, I>(ctx: &BindgenContext, for (name, offset, width, bitfield_ty, bitfield_layout) in bitfields { let prefix = ctx.trait_prefix(); - let getter_name = ctx.rust_ident(name); - let setter_name = ctx.ext_cx() - .ident_of(&format!("set_{}", &name)); + let getter_name = bitfield_getter_name(ctx, parent, name); + let setter_name = bitfield_setter_name(ctx, parent, name); let field_ident = ctx.ext_cx().ident_of(field_name); let field_int_ty = match field_layout.size { @@ -1184,7 +1233,7 @@ impl CodeGenerator for CompInfo { mem::replace(&mut current_bitfield_fields, vec![]); let bitfield_layout = Bitfield::new(&mut bitfield_count, bitfield_fields) - .codegen_fields(ctx, &mut fields, &mut methods); + .codegen_fields(ctx, self, &mut fields, &mut methods); struct_layout.saw_bitfield_batch(bitfield_layout); current_bitfield_width = None; @@ -1339,7 +1388,7 @@ impl CodeGenerator for CompInfo { vec![]); let bitfield_layout = Bitfield::new(&mut bitfield_count, bitfield_fields) - .codegen_fields(ctx, &mut fields, &mut methods); + .codegen_fields(ctx, self, &mut fields, &mut methods); struct_layout.saw_bitfield_batch(bitfield_layout); } debug_assert!(current_bitfield_fields.is_empty()); diff --git a/tests/expectations/tests/bitfield-method-same-name.rs b/tests/expectations/tests/bitfield-method-same-name.rs new file mode 100644 index 00000000..9222f74d --- /dev/null +++ b/tests/expectations/tests/bitfield-method-same-name.rs @@ -0,0 +1,67 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct Foo { + pub _bitfield_1: u8, + pub __bindgen_align: [u8; 0usize], +} +#[test] +fn bindgen_test_layout_Foo() { + assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! ( + "Size of: " , stringify ! ( Foo ) )); + assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! ( + "Alignment of " , stringify ! ( Foo ) )); +} +extern "C" { + #[link_name = "_ZN3Foo4typeEv"] + pub fn Foo_type(this: *mut Foo) -> ::std::os::raw::c_schar; +} +extern "C" { + #[link_name = "_ZN3Foo9set_type_Ec"] + pub fn Foo_set_type_(this: *mut Foo, c: ::std::os::raw::c_schar); +} +extern "C" { + #[link_name = "_ZN3Foo8set_typeEc"] + pub fn Foo_set_type(this: *mut Foo, c: ::std::os::raw::c_schar); +} +impl Clone for Foo { + fn clone(&self) -> Self { *self } +} +impl Foo { + #[inline] + pub fn type__bindgen_bitfield(&self) -> ::std::os::raw::c_schar { + let mask = 7usize as u8; + let field_val: u8 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + let val = (field_val & mask) >> 0usize; + unsafe { ::std::mem::transmute(val as u8) } + } + #[inline] + pub fn set_type__bindgen_bitfield(&mut self, + val: ::std::os::raw::c_schar) { + let mask = 7usize as u8; + let val = val as u8 as u8; + let mut field_val: u8 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + field_val &= !mask; + field_val |= (val << 0usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(field_val) }; + } + #[inline] + pub unsafe fn type_(&mut self) -> ::std::os::raw::c_schar { + Foo_type(&mut *self) + } + #[inline] + pub unsafe fn set_type_(&mut self, c: ::std::os::raw::c_schar) { + Foo_set_type_(&mut *self, c) + } + #[inline] + pub unsafe fn set_type(&mut self, c: ::std::os::raw::c_schar) { + Foo_set_type(&mut *self, c) + } +} diff --git a/tests/headers/bitfield-method-same-name.hpp b/tests/headers/bitfield-method-same-name.hpp new file mode 100644 index 00000000..d66f16c0 --- /dev/null +++ b/tests/headers/bitfield-method-same-name.hpp @@ -0,0 +1,6 @@ +struct Foo { + char type_ : 3; + char type(); + void set_type_(char c); + void set_type(char c); +}; |