Skip to content

Commit 53c5e2c

Browse files
committed
Give vtables and anonymous items more stable generated names.
1 parent b903022 commit 53c5e2c

38 files changed

+271
-293
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ quasi_codegen = "0.20"
2323

2424
[dependencies]
2525
clang-sys = "0.8.0"
26+
lazy_static = "0.1.*"
2627
libc = "0.2"
2728
log = "0.3"
2829
env_logger = "0.3"

src/codegen/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,8 @@ impl<'a> CodeGenerator for Vtable<'a> {
445445
}
446446

447447
impl<'a> ItemCanonicalName for Vtable<'a> {
448-
fn canonical_name(&self, _ctx: &BindgenContext) -> String {
449-
format!("bindgen_vtable_{}", self.item_id)
448+
fn canonical_name(&self, ctx: &BindgenContext) -> String {
449+
format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx))
450450
}
451451
}
452452

src/ir/item.rs

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
use regex::Regex;
12
use super::context::BindgenContext;
23
use super::item_kind::ItemKind;
34
use super::ty::{Type, TypeKind};
45
use super::function::Function;
56
use super::module::Module;
67
use super::annotations::Annotations;
7-
use std::fmt;
8+
use std::cell::Cell;
89
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
910
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
1011
use clang;
@@ -46,13 +47,6 @@ pub trait ItemCanonicalPath {
4647
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
4748
pub struct ItemId(usize);
4849

49-
impl fmt::Display for ItemId {
50-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
51-
try!(write!(fmt, "_bindgen_id_"));
52-
self.0.fmt(fmt)
53-
}
54-
}
55-
5650
pub static NEXT_ITEM_ID: AtomicUsize = ATOMIC_USIZE_INIT;
5751

5852
impl ItemId {
@@ -96,6 +90,11 @@ impl ItemCanonicalPath for ItemId {
9690
pub struct Item {
9791
/// This item's id.
9892
id: ItemId,
93+
/// The item's local id, unique only amongst its siblings. Only used
94+
/// for anonymous items. Lazily initialized in local_id().
95+
local_id: Cell<Option<usize>>,
96+
/// The next local id to use for a child.
97+
next_child_local_id: AtomicUsize,
9998
/// A doc comment over the item, if any.
10099
comment: Option<String>,
101100
/// Annotations extracted from the doc comment, or the default ones
@@ -120,6 +119,8 @@ impl Item {
120119
debug_assert!(id != parent_id || kind.is_module());
121120
Item {
122121
id: id,
122+
local_id: Cell::new(None),
123+
next_child_local_id: AtomicUsize::new(1),
123124
parent_id: parent_id,
124125
comment: comment,
125126
annotations: annotations.unwrap_or_default(),
@@ -147,6 +148,15 @@ impl Item {
147148
&mut self.kind
148149
}
149150

151+
pub fn local_id(&self, ctx: &BindgenContext) -> usize {
152+
if self.local_id.get().is_none() {
153+
let parent = ctx.resolve_item(self.parent_id);
154+
let local_id = parent.next_child_local_id.fetch_add(1, Ordering::Relaxed);
155+
self.local_id.set(Some(local_id));
156+
}
157+
self.local_id.get().unwrap()
158+
}
159+
150160
/// Returns whether this item is a top-level item, from the point of view of
151161
/// bindgen.
152162
///
@@ -435,7 +445,6 @@ impl Item {
435445
ty.name()
436446
}
437447
}.map(ToOwned::to_owned)
438-
.unwrap_or_else(|| format!("_bindgen_ty{}", self.id()))
439448
}
440449
ItemKind::Function(ref fun) => {
441450
let mut base = fun.name().to_owned();
@@ -464,30 +473,53 @@ impl Item {
464473
}
465474
}
466475
}
467-
base
476+
Some(base)
468477
}
469478
ItemKind::Var(ref var) => {
470-
var.name().to_owned()
479+
Some(var.name().to_owned())
471480
}
472481
ItemKind::Module(ref module) => {
473482
module.name().map(ToOwned::to_owned)
474-
.unwrap_or_else(|| format!("_bindgen_mod{}", self.id()))
475483
}
476484
};
477485

478486
let parent = ctx.resolve_item(self.parent_id());
479487
let parent_is_namespace = parent.is_module();
488+
480489
if self.is_toplevel(ctx) || (parent_is_namespace && count_namespaces) {
490+
let base_name = self.make_local_name(None, base_name, ctx);
481491
return ctx.rust_mangle(&base_name).into_owned();
482492
}
483493

484494
// TODO: allow modification of the mangling functions, maybe even per
485495
// item type?
486-
let parent = parent.canonical_name(ctx);
487-
if parent.is_empty() {
488-
base_name.to_owned()
489-
} else {
490-
format!("{}_{}", parent, base_name)
496+
let parent_name = parent.canonical_name(ctx);
497+
self.make_local_name(Some(parent_name), base_name, ctx)
498+
}
499+
500+
fn make_local_name(&self,
501+
parent_name: Option<String>,
502+
base_name: Option<String>,
503+
ctx: &BindgenContext) -> String {
504+
lazy_static! {
505+
static ref RE_ENDS_WITH_BINDGEN_TY: Regex = Regex::new(r"_bindgen_ty_\d+$").unwrap();
506+
static ref RE_ENDS_WITH_BINDGEN_MOD: Regex = Regex::new(r"_bindgen_mod_\d+$").unwrap();
507+
}
508+
let (re, kind) = match *self.kind() {
509+
ItemKind::Module(..) => (&*RE_ENDS_WITH_BINDGEN_MOD, "mod"),
510+
_ => (&*RE_ENDS_WITH_BINDGEN_TY, "ty"),
511+
};
512+
match (parent_name, base_name) {
513+
(Some(parent), Some(base)) => format!("{}_{}", parent, base),
514+
(Some(parent), None) => {
515+
if re.is_match(parent.as_str()) {
516+
format!("{}_{}", parent, self.local_id(ctx))
517+
} else {
518+
format!("{}__bindgen_{}_{}", parent, kind, self.local_id(ctx))
519+
}
520+
}
521+
(None, Some(base)) => base,
522+
(None, None) => format!("_bindgen_{}_{}", kind, self.local_id(ctx)),
491523
}
492524
}
493525

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ extern crate libc;
1616
extern crate regex;
1717
#[macro_use]
1818
extern crate log;
19+
#[macro_use]
20+
extern crate lazy_static;
1921

2022
mod clangll;
2123
mod clang;

tests/expectations/anon_enum.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ pub struct Test {
1010
pub foo: ::std::os::raw::c_int,
1111
pub bar: f32,
1212
}
13-
pub const Test_T_NONE: Test__bindgen_ty_bindgen_id_6 =
14-
Test__bindgen_ty_bindgen_id_6::T_NONE;
13+
pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE;
1514
#[repr(u32)]
1615
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
17-
pub enum Test__bindgen_ty_bindgen_id_6 { T_NONE = 0, }
16+
pub enum Test__bindgen_ty_1 { T_NONE = 0, }
1817
#[test]
1918
fn bindgen_test_layout_Test() {
2019
assert_eq!(::std::mem::size_of::<Test>() , 8usize);

tests/expectations/anon_enum_whitelist.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
#![allow(non_snake_case)]
55

66

7-
pub const NODE_FLAG_FOO: _bindgen_ty_bindgen_id_1 =
8-
_bindgen_ty_bindgen_id_1::NODE_FLAG_FOO;
9-
pub const NODE_FLAG_BAR: _bindgen_ty_bindgen_id_1 =
10-
_bindgen_ty_bindgen_id_1::NODE_FLAG_BAR;
7+
pub const NODE_FLAG_FOO: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_FOO;
8+
pub const NODE_FLAG_BAR: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_BAR;
119
#[repr(u32)]
1210
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
13-
pub enum _bindgen_ty_bindgen_id_1 { NODE_FLAG_FOO = 0, NODE_FLAG_BAR = 1, }
11+
pub enum _bindgen_ty_1 { NODE_FLAG_FOO = 0, NODE_FLAG_BAR = 1, }

tests/expectations/anon_union.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
2828
#[derive(Debug, Copy, Clone)]
2929
pub struct TErrorResult<T> {
3030
pub mResult: ::std::os::raw::c_int,
31-
pub __bindgen_anon_1: TErrorResult__bindgen_ty_bindgen_id_10<T>,
31+
pub __bindgen_anon_1: TErrorResult__bindgen_ty_1<T>,
3232
pub mMightHaveUnreported: bool,
3333
pub mUnionState: TErrorResult_UnionState,
3434
pub _phantom_0: ::std::marker::PhantomData<T>,
@@ -52,7 +52,7 @@ pub struct TErrorResult_DOMExceptionInfo<T> {
5252
}
5353
#[repr(C)]
5454
#[derive(Debug, Copy, Clone)]
55-
pub struct TErrorResult__bindgen_ty_bindgen_id_10<T> {
55+
pub struct TErrorResult__bindgen_ty_1<T> {
5656
pub mMessage: __BindgenUnionField<*mut TErrorResult_Message<T>>,
5757
pub mDOMExceptionInfo: __BindgenUnionField<*mut TErrorResult_DOMExceptionInfo<T>>,
5858
pub bindgen_union_field: u64,

tests/expectations/class_with_inner_struct.rs

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
2828
#[derive(Debug, Copy)]
2929
pub struct A {
3030
pub c: ::std::os::raw::c_uint,
31-
pub named_union: A__bindgen_ty_bindgen_id_9,
32-
pub __bindgen_anon_1: A__bindgen_ty_bindgen_id_14,
31+
pub named_union: A__bindgen_ty_1,
32+
pub __bindgen_anon_1: A__bindgen_ty_2,
3333
}
3434
#[repr(C)]
3535
#[derive(Debug, Copy)]
@@ -47,31 +47,30 @@ impl Clone for A_Segment {
4747
}
4848
#[repr(C)]
4949
#[derive(Debug, Copy)]
50-
pub struct A__bindgen_ty_bindgen_id_9 {
50+
pub struct A__bindgen_ty_1 {
5151
pub f: __BindgenUnionField<::std::os::raw::c_int>,
5252
pub bindgen_union_field: u32,
5353
}
5454
#[test]
55-
fn bindgen_test_layout_A__bindgen_ty_bindgen_id_9() {
56-
assert_eq!(::std::mem::size_of::<A__bindgen_ty_bindgen_id_9>() , 4usize);
57-
assert_eq!(::std::mem::align_of::<A__bindgen_ty_bindgen_id_9>() , 4usize);
55+
fn bindgen_test_layout_A__bindgen_ty_1() {
56+
assert_eq!(::std::mem::size_of::<A__bindgen_ty_1>() , 4usize);
57+
assert_eq!(::std::mem::align_of::<A__bindgen_ty_1>() , 4usize);
5858
}
59-
impl Clone for A__bindgen_ty_bindgen_id_9 {
59+
impl Clone for A__bindgen_ty_1 {
6060
fn clone(&self) -> Self { *self }
6161
}
6262
#[repr(C)]
6363
#[derive(Debug, Copy)]
64-
pub struct A__bindgen_ty_bindgen_id_14 {
64+
pub struct A__bindgen_ty_2 {
6565
pub d: __BindgenUnionField<::std::os::raw::c_int>,
6666
pub bindgen_union_field: u32,
6767
}
6868
#[test]
69-
fn bindgen_test_layout_A__bindgen_ty_bindgen_id_14() {
70-
assert_eq!(::std::mem::size_of::<A__bindgen_ty_bindgen_id_14>() , 4usize);
71-
assert_eq!(::std::mem::align_of::<A__bindgen_ty_bindgen_id_14>() ,
72-
4usize);
69+
fn bindgen_test_layout_A__bindgen_ty_2() {
70+
assert_eq!(::std::mem::size_of::<A__bindgen_ty_2>() , 4usize);
71+
assert_eq!(::std::mem::align_of::<A__bindgen_ty_2>() , 4usize);
7372
}
74-
impl Clone for A__bindgen_ty_bindgen_id_14 {
73+
impl Clone for A__bindgen_ty_2 {
7574
fn clone(&self) -> Self { *self }
7675
}
7776
#[test]
@@ -121,57 +120,51 @@ pub enum StepSyntax {
121120
#[derive(Debug, Copy)]
122121
pub struct C {
123122
pub d: ::std::os::raw::c_uint,
124-
pub __bindgen_anon_1: C__bindgen_ty_bindgen_id_31,
123+
pub __bindgen_anon_1: C__bindgen_ty_1,
125124
}
126125
#[repr(C)]
127126
#[derive(Debug, Copy)]
128-
pub struct C__bindgen_ty_bindgen_id_31 {
129-
pub mFunc: __BindgenUnionField<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32>,
130-
pub __bindgen_anon_1: __BindgenUnionField<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43>,
127+
pub struct C__bindgen_ty_1 {
128+
pub mFunc: __BindgenUnionField<C__bindgen_ty_1_1>,
129+
pub __bindgen_anon_1: __BindgenUnionField<C__bindgen_ty_1_2>,
131130
pub bindgen_union_field: [u32; 4usize],
132131
}
133132
#[repr(C)]
134133
#[derive(Debug, Copy)]
135-
pub struct C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32 {
134+
pub struct C__bindgen_ty_1_1 {
136135
pub mX1: f32,
137136
pub mY1: f32,
138137
pub mX2: f32,
139138
pub mY2: f32,
140139
}
141140
#[test]
142-
fn bindgen_test_layout_C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32() {
143-
assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32>()
144-
, 16usize);
145-
assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32>()
146-
, 4usize);
141+
fn bindgen_test_layout_C__bindgen_ty_1_1() {
142+
assert_eq!(::std::mem::size_of::<C__bindgen_ty_1_1>() , 16usize);
143+
assert_eq!(::std::mem::align_of::<C__bindgen_ty_1_1>() , 4usize);
147144
}
148-
impl Clone for C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32 {
145+
impl Clone for C__bindgen_ty_1_1 {
149146
fn clone(&self) -> Self { *self }
150147
}
151148
#[repr(C)]
152149
#[derive(Debug, Copy)]
153-
pub struct C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43 {
150+
pub struct C__bindgen_ty_1_2 {
154151
pub mStepSyntax: StepSyntax,
155152
pub mSteps: ::std::os::raw::c_uint,
156153
}
157154
#[test]
158-
fn bindgen_test_layout_C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43() {
159-
assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43>()
160-
, 8usize);
161-
assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43>()
162-
, 4usize);
155+
fn bindgen_test_layout_C__bindgen_ty_1_2() {
156+
assert_eq!(::std::mem::size_of::<C__bindgen_ty_1_2>() , 8usize);
157+
assert_eq!(::std::mem::align_of::<C__bindgen_ty_1_2>() , 4usize);
163158
}
164-
impl Clone for C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43 {
159+
impl Clone for C__bindgen_ty_1_2 {
165160
fn clone(&self) -> Self { *self }
166161
}
167162
#[test]
168-
fn bindgen_test_layout_C__bindgen_ty_bindgen_id_31() {
169-
assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_31>() ,
170-
16usize);
171-
assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_31>() ,
172-
4usize);
163+
fn bindgen_test_layout_C__bindgen_ty_1() {
164+
assert_eq!(::std::mem::size_of::<C__bindgen_ty_1>() , 16usize);
165+
assert_eq!(::std::mem::align_of::<C__bindgen_ty_1>() , 4usize);
173166
}
174-
impl Clone for C__bindgen_ty_bindgen_id_31 {
167+
impl Clone for C__bindgen_ty_1 {
175168
fn clone(&self) -> Self { *self }
176169
}
177170
#[repr(C)]

tests/expectations/const_enum_unnamed.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,20 @@
44
#![allow(non_snake_case)]
55

66

7-
pub const FOO_BAR: _bindgen_ty_bindgen_id_1 =
8-
_bindgen_ty_bindgen_id_1::FOO_BAR;
9-
pub const FOO_BAZ: _bindgen_ty_bindgen_id_1 =
10-
_bindgen_ty_bindgen_id_1::FOO_BAZ;
7+
pub const FOO_BAR: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAR;
8+
pub const FOO_BAZ: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAZ;
119
#[repr(u32)]
1210
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
13-
pub enum _bindgen_ty_bindgen_id_1 { FOO_BAR = 0, FOO_BAZ = 1, }
11+
pub enum _bindgen_ty_1 { FOO_BAR = 0, FOO_BAZ = 1, }
1412
#[repr(C)]
1513
#[derive(Debug, Copy)]
1614
pub struct Foo {
1715
pub _address: u8,
1816
}
19-
pub const Foo_FOO_BAR: Foo__bindgen_ty_bindgen_id_5 =
20-
Foo__bindgen_ty_bindgen_id_5::FOO_BAR;
17+
pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR;
2118
#[repr(u32)]
2219
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
23-
pub enum Foo__bindgen_ty_bindgen_id_5 { FOO_BAR = 10, }
20+
pub enum Foo__bindgen_ty_1 { FOO_BAR = 10, }
2421
#[test]
2522
fn bindgen_test_layout_Foo() {
2623
assert_eq!(::std::mem::size_of::<Foo>() , 1usize);

tests/expectations/enum_and_vtable_mangling.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,18 @@
44
#![allow(non_snake_case)]
55

66

7-
pub const match_: _bindgen_ty_bindgen_id_1 = _bindgen_ty_bindgen_id_1::match_;
8-
pub const whatever_else: _bindgen_ty_bindgen_id_1 =
9-
_bindgen_ty_bindgen_id_1::whatever_else;
7+
pub const match_: _bindgen_ty_1 = _bindgen_ty_1::match_;
8+
pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else;
109
#[repr(u32)]
1110
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
12-
pub enum _bindgen_ty_bindgen_id_1 { match_ = 0, whatever_else = 1, }
11+
pub enum _bindgen_ty_1 { match_ = 0, whatever_else = 1, }
1312
#[repr(C)]
14-
pub struct bindgen_vtable__bindgen_id_4 {
13+
pub struct C__bindgen_vtable {
1514
}
1615
#[repr(C)]
1716
#[derive(Debug, Copy)]
1817
pub struct C {
19-
pub vtable_: *const bindgen_vtable__bindgen_id_4,
18+
pub vtable_: *const C__bindgen_vtable,
2019
pub i: ::std::os::raw::c_int,
2120
}
2221
#[test]

0 commit comments

Comments
 (0)