Skip to content

Commit 74f6599

Browse files
author
bors-servo
authored
Auto merge of #589 - fitzgen:conflicting-methods-and-bitfield-accessors, r=emilio
Resolve namespace clashes between methods and generated bitfield accessors This commit makes bitfields' accessor codegen detect conflicting method names and generate alternative, non-conflicting names instead. Yes, I really hit this in SpiderMonkey... r? @emilio
2 parents 5452ad0 + 0890603 commit 74f6599

File tree

3 files changed

+127
-5
lines changed

3 files changed

+127
-5
lines changed

src/codegen/mod.rs

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ impl<'a> Bitfield<'a> {
753753

754754
fn codegen_fields(self,
755755
ctx: &BindgenContext,
756+
parent: &CompInfo,
756757
fields: &mut Vec<ast::StructField>,
757758
methods: &mut Vec<ast::ImplItem>)
758759
-> Layout {
@@ -790,6 +791,7 @@ impl<'a> Bitfield<'a> {
790791
// We've finished a physical field, so flush it and its bitfields.
791792
field_size_in_bits = align_to(field_size_in_bits, field_align);
792793
fields.push(flush_bitfields(ctx,
794+
parent,
793795
field_size_in_bits,
794796
last_field_align,
795797
&last_field_name,
@@ -831,6 +833,7 @@ impl<'a> Bitfield<'a> {
831833
if field_size_in_bits != 0 {
832834
// Flush the last physical field and its bitfields.
833835
fields.push(flush_bitfields(ctx,
836+
parent,
834837
field_size_in_bits,
835838
last_field_align,
836839
&last_field_name,
@@ -842,12 +845,59 @@ impl<'a> Bitfield<'a> {
842845
}
843846
}
844847

848+
fn parent_has_method(ctx: &BindgenContext,
849+
parent: &CompInfo,
850+
name: &str)
851+
-> bool {
852+
parent.methods().iter().any(|method| {
853+
let method_name = match *ctx.resolve_item(method.signature()).kind() {
854+
ItemKind::Function(ref func) => func.name(),
855+
ref otherwise => panic!("a method's signature should always be a \
856+
item of kind ItemKind::Function, found: \
857+
{:?}",
858+
otherwise),
859+
};
860+
861+
method_name == name || ctx.rust_mangle(&method_name) == name
862+
})
863+
}
864+
865+
fn bitfield_getter_name(ctx: &BindgenContext,
866+
parent: &CompInfo,
867+
bitfield_name: &str)
868+
-> ast::Ident {
869+
let name = ctx.rust_mangle(bitfield_name);
870+
871+
if parent_has_method(ctx, parent, &name) {
872+
let mut name = name.to_string();
873+
name.push_str("_bindgen_bitfield");
874+
return ctx.ext_cx().ident_of(&name);
875+
}
876+
877+
ctx.ext_cx().ident_of(&name)
878+
}
879+
880+
fn bitfield_setter_name(ctx: &BindgenContext,
881+
parent: &CompInfo,
882+
bitfield_name: &str)
883+
-> ast::Ident {
884+
let setter = format!("set_{}", bitfield_name);
885+
let mut setter = ctx.rust_mangle(&setter).to_string();
886+
887+
if parent_has_method(ctx, parent, &setter) {
888+
setter.push_str("_bindgen_bitfield");
889+
}
890+
891+
ctx.ext_cx().ident_of(&setter)
892+
}
893+
845894
/// A physical field (which is a word or byte or ...) has many logical bitfields
846895
/// contained within it, but not all bitfields are in the same physical field of
847896
/// a struct. This function creates a single physical field and flushes all the
848897
/// accessors for the logical `bitfields` within that physical field to the
849898
/// outgoing `methods`.
850899
fn flush_bitfields<'a, I>(ctx: &BindgenContext,
900+
parent: &CompInfo,
851901
field_size_in_bits: usize,
852902
field_align: usize,
853903
field_name: &str,
@@ -867,9 +917,8 @@ fn flush_bitfields<'a, I>(ctx: &BindgenContext,
867917

868918
for (name, offset, width, bitfield_ty, bitfield_layout) in bitfields {
869919
let prefix = ctx.trait_prefix();
870-
let getter_name = ctx.rust_ident(name);
871-
let setter_name = ctx.ext_cx()
872-
.ident_of(&format!("set_{}", &name));
920+
let getter_name = bitfield_getter_name(ctx, parent, name);
921+
let setter_name = bitfield_setter_name(ctx, parent, name);
873922
let field_ident = ctx.ext_cx().ident_of(field_name);
874923

875924
let field_int_ty = match field_layout.size {
@@ -1184,7 +1233,7 @@ impl CodeGenerator for CompInfo {
11841233
mem::replace(&mut current_bitfield_fields, vec![]);
11851234
let bitfield_layout = Bitfield::new(&mut bitfield_count,
11861235
bitfield_fields)
1187-
.codegen_fields(ctx, &mut fields, &mut methods);
1236+
.codegen_fields(ctx, self, &mut fields, &mut methods);
11881237
struct_layout.saw_bitfield_batch(bitfield_layout);
11891238

11901239
current_bitfield_width = None;
@@ -1339,7 +1388,7 @@ impl CodeGenerator for CompInfo {
13391388
vec![]);
13401389
let bitfield_layout = Bitfield::new(&mut bitfield_count,
13411390
bitfield_fields)
1342-
.codegen_fields(ctx, &mut fields, &mut methods);
1391+
.codegen_fields(ctx, self, &mut fields, &mut methods);
13431392
struct_layout.saw_bitfield_batch(bitfield_layout);
13441393
}
13451394
debug_assert!(current_bitfield_fields.is_empty());
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Default, Copy)]
9+
pub struct Foo {
10+
pub _bitfield_1: u8,
11+
pub __bindgen_align: [u8; 0usize],
12+
}
13+
#[test]
14+
fn bindgen_test_layout_Foo() {
15+
assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! (
16+
"Size of: " , stringify ! ( Foo ) ));
17+
assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! (
18+
"Alignment of " , stringify ! ( Foo ) ));
19+
}
20+
extern "C" {
21+
#[link_name = "_ZN3Foo4typeEv"]
22+
pub fn Foo_type(this: *mut Foo) -> ::std::os::raw::c_schar;
23+
}
24+
extern "C" {
25+
#[link_name = "_ZN3Foo9set_type_Ec"]
26+
pub fn Foo_set_type_(this: *mut Foo, c: ::std::os::raw::c_schar);
27+
}
28+
extern "C" {
29+
#[link_name = "_ZN3Foo8set_typeEc"]
30+
pub fn Foo_set_type(this: *mut Foo, c: ::std::os::raw::c_schar);
31+
}
32+
impl Clone for Foo {
33+
fn clone(&self) -> Self { *self }
34+
}
35+
impl Foo {
36+
#[inline]
37+
pub fn type__bindgen_bitfield(&self) -> ::std::os::raw::c_schar {
38+
let mask = 7usize as u8;
39+
let field_val: u8 =
40+
unsafe { ::std::mem::transmute(self._bitfield_1) };
41+
let val = (field_val & mask) >> 0usize;
42+
unsafe { ::std::mem::transmute(val as u8) }
43+
}
44+
#[inline]
45+
pub fn set_type__bindgen_bitfield(&mut self,
46+
val: ::std::os::raw::c_schar) {
47+
let mask = 7usize as u8;
48+
let val = val as u8 as u8;
49+
let mut field_val: u8 =
50+
unsafe { ::std::mem::transmute(self._bitfield_1) };
51+
field_val &= !mask;
52+
field_val |= (val << 0usize) & mask;
53+
self._bitfield_1 = unsafe { ::std::mem::transmute(field_val) };
54+
}
55+
#[inline]
56+
pub unsafe fn type_(&mut self) -> ::std::os::raw::c_schar {
57+
Foo_type(&mut *self)
58+
}
59+
#[inline]
60+
pub unsafe fn set_type_(&mut self, c: ::std::os::raw::c_schar) {
61+
Foo_set_type_(&mut *self, c)
62+
}
63+
#[inline]
64+
pub unsafe fn set_type(&mut self, c: ::std::os::raw::c_schar) {
65+
Foo_set_type(&mut *self, c)
66+
}
67+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
struct Foo {
2+
char type_ : 3;
3+
char type();
4+
void set_type_(char c);
5+
void set_type(char c);
6+
};

0 commit comments

Comments
 (0)