summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs59
-rw-r--r--tests/expectations/tests/bitfield-method-same-name.rs67
-rw-r--r--tests/headers/bitfield-method-same-name.hpp6
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);
+};