Skip to content

Commit ca99ef3

Browse files
committed
Use BindgenContext::whitelisted_items in code generation
This replaces the manual gathering and traversal of the transitive closure of whitelisted items with the new canonical method.
1 parent 3273506 commit ca99ef3

7 files changed

+98
-158
lines changed

src/codegen/mod.rs

Lines changed: 33 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use ir::item_kind::ItemKind;
1414
use ir::layout::Layout;
1515
use ir::module::Module;
1616
use ir::ty::{Type, TypeKind};
17-
use ir::type_collector::{ItemSet, TypeCollector};
17+
use ir::type_collector::ItemSet;
1818
use ir::var::Var;
1919
use self::helpers::{BlobTyBuilder, attributes};
2020

@@ -1692,108 +1692,48 @@ impl CodeGenerator for Function {
16921692
}
16931693
}
16941694

1695+
// Return true if any of the ancestors of `id` are in the whitelisted items set,
1696+
// false otherwise.
1697+
fn ancestor_is_whitelisted(ctx: &BindgenContext,
1698+
whitelisted_items: &ItemSet,
1699+
id: ItemId)
1700+
-> bool {
1701+
let item = ctx.resolve_item(id);
1702+
let mut last = id;
1703+
let mut current = item.parent_id();
1704+
1705+
while last != current {
1706+
if whitelisted_items.contains(&current) {
1707+
return true;
1708+
}
1709+
last = current;
1710+
current = ctx.resolve_item(current).parent_id();
1711+
}
1712+
1713+
false
1714+
}
1715+
16951716
pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
16961717
context.gen(|context| {
16971718
let mut result = CodegenResult::new();
16981719

16991720
debug!("codegen: {:?}", context.options());
17001721

1701-
// If the whitelisted types and functions sets are empty, just generate
1702-
// everything.
1703-
if context.options().whitelisted_types.is_empty() &&
1704-
context.options().whitelisted_functions.is_empty() &&
1705-
context.options().whitelisted_vars.is_empty() {
1706-
for (_item_id, item) in context.items() {
1707-
// Non-toplevel item parents are the responsible one for
1708-
// generating them.
1709-
if item.is_toplevel(context) {
1710-
item.codegen(context, &mut result, &());
1711-
}
1712-
}
1713-
} else {
1714-
// Recursively collect all the types dependent on the whitelisted
1715-
// types, then generate them.
1716-
//
1717-
// FIXME(emilio): This pass is probably slow, but it can't be faster
1718-
// than docopt anyway :)
1719-
let mut items = ItemSet::new();
1720-
for (_item_id, item) in context.items() {
1721-
// FIXME(emilio): This probably should look only at whether the
1722-
// parent is a module.
1723-
if !item.is_toplevel(context) {
1724-
continue;
1725-
}
1726-
1727-
let name = item.canonical_name(context);
1728-
match *item.kind() {
1729-
ItemKind::Type(ref ty) => {
1730-
if context.options().whitelisted_types.matches(&name) {
1731-
item.collect_types(context, &mut items, &());
1732-
}
1733-
// Unnamed top-level enums are special and we whitelist
1734-
// them via the whitelisted_vars filter, since they're
1735-
// effectively top-level constants, and there's no way
1736-
// for them to be referenced consistently.
1737-
if let TypeKind::Enum(ref enum_) = *ty.kind() {
1738-
if ty.name().is_none() {
1739-
if enum_.variants().iter().any(|variant| {
1740-
context.options()
1741-
.whitelisted_vars
1742-
.matches(&variant.name())
1743-
}) {
1744-
item.collect_types(context,
1745-
&mut items,
1746-
&());
1747-
}
1748-
}
1749-
}
1750-
}
1751-
ItemKind::Function(ref fun) => {
1752-
if context.options()
1753-
.whitelisted_functions
1754-
.matches(&name) {
1755-
items.insert(item.id());
1756-
fun.signature()
1757-
.collect_types(context, &mut items, &());
1758-
}
1759-
}
1760-
ItemKind::Var(ref var) => {
1761-
if context.options().whitelisted_vars.matches(&name) {
1762-
items.insert(item.id());
1763-
var.ty().collect_types(context, &mut items, &());
1764-
}
1765-
}
1766-
ItemKind::Module(..) => {}
1767-
}
1768-
}
1769-
1770-
fn contains_parent(ctx: &BindgenContext,
1771-
types: &ItemSet,
1772-
id: ItemId)
1773-
-> bool {
1774-
let item = ctx.resolve_item(id);
1775-
let mut last = id;
1776-
let mut current = item.parent_id();
1777-
1778-
while last != current {
1779-
if types.contains(&current) {
1780-
return true;
1781-
}
1782-
last = current;
1783-
current = ctx.resolve_item(current).parent_id();
1784-
}
1722+
let whitelisted_items: ItemSet = context.whitelisted_items().collect();
17851723

1786-
false
1787-
}
1724+
for &id in whitelisted_items.iter() {
1725+
let item = context.resolve_item(id);
17881726

1789-
for item_id in items.iter() {
1790-
let item = context.resolve_item(*item_id);
1791-
if item.is_toplevel(context) ||
1792-
!contains_parent(context, &items, *item_id) {
1793-
item.codegen(context, &mut result, &());
1794-
}
1727+
// Non-toplevel items' parents are responsible one for generating
1728+
// their children. However, if we find an orphaned reference to a
1729+
// non-toplevel item whose parent is not in our whitelisted set, we
1730+
// need to take responsibility for generating it.
1731+
if item.is_toplevel(context) ||
1732+
!ancestor_is_whitelisted(context, &whitelisted_items, id) {
1733+
item.codegen(context, &mut result, &());
17951734
}
17961735
}
1736+
17971737
let saw_union = result.saw_union;
17981738
let mut result = result.items;
17991739
if saw_union && !context.options().unstable_rust {

tests/expectations/class_with_inner_struct.rs

Lines changed: 24 additions & 24 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_1,
32-
pub __bindgen_anon_1: A__bindgen_ty_2,
31+
pub named_union: A__bindgen_ty_2,
32+
pub __bindgen_anon_1: A__bindgen_ty_1,
3333
}
3434
#[repr(C)]
3535
#[derive(Debug, Copy)]
@@ -47,30 +47,30 @@ impl Clone for A_Segment {
4747
}
4848
#[repr(C)]
4949
#[derive(Debug, Copy)]
50-
pub struct A__bindgen_ty_1 {
50+
pub struct A__bindgen_ty_2 {
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_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);
55+
fn bindgen_test_layout_A__bindgen_ty_2() {
56+
assert_eq!(::std::mem::size_of::<A__bindgen_ty_2>() , 4usize);
57+
assert_eq!(::std::mem::align_of::<A__bindgen_ty_2>() , 4usize);
5858
}
59-
impl Clone for A__bindgen_ty_1 {
59+
impl Clone for A__bindgen_ty_2 {
6060
fn clone(&self) -> Self { *self }
6161
}
6262
#[repr(C)]
6363
#[derive(Debug, Copy)]
64-
pub struct A__bindgen_ty_2 {
64+
pub struct A__bindgen_ty_1 {
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_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);
69+
fn bindgen_test_layout_A__bindgen_ty_1() {
70+
assert_eq!(::std::mem::size_of::<A__bindgen_ty_1>() , 4usize);
71+
assert_eq!(::std::mem::align_of::<A__bindgen_ty_1>() , 4usize);
7272
}
73-
impl Clone for A__bindgen_ty_2 {
73+
impl Clone for A__bindgen_ty_1 {
7474
fn clone(&self) -> Self { *self }
7575
}
7676
#[test]
@@ -125,38 +125,38 @@ pub struct C {
125125
#[repr(C)]
126126
#[derive(Debug, Copy)]
127127
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>,
128+
pub mFunc: __BindgenUnionField<C__bindgen_ty_1_2>,
129+
pub __bindgen_anon_1: __BindgenUnionField<C__bindgen_ty_1_1>,
130130
pub bindgen_union_field: [u32; 4usize],
131131
}
132132
#[repr(C)]
133133
#[derive(Debug, Copy)]
134-
pub struct C__bindgen_ty_1_1 {
134+
pub struct C__bindgen_ty_1_2 {
135135
pub mX1: f32,
136136
pub mY1: f32,
137137
pub mX2: f32,
138138
pub mY2: f32,
139139
}
140140
#[test]
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);
141+
fn bindgen_test_layout_C__bindgen_ty_1_2() {
142+
assert_eq!(::std::mem::size_of::<C__bindgen_ty_1_2>() , 16usize);
143+
assert_eq!(::std::mem::align_of::<C__bindgen_ty_1_2>() , 4usize);
144144
}
145-
impl Clone for C__bindgen_ty_1_1 {
145+
impl Clone for C__bindgen_ty_1_2 {
146146
fn clone(&self) -> Self { *self }
147147
}
148148
#[repr(C)]
149149
#[derive(Debug, Copy)]
150-
pub struct C__bindgen_ty_1_2 {
150+
pub struct C__bindgen_ty_1_1 {
151151
pub mStepSyntax: StepSyntax,
152152
pub mSteps: ::std::os::raw::c_uint,
153153
}
154154
#[test]
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);
155+
fn bindgen_test_layout_C__bindgen_ty_1_1() {
156+
assert_eq!(::std::mem::size_of::<C__bindgen_ty_1_1>() , 8usize);
157+
assert_eq!(::std::mem::align_of::<C__bindgen_ty_1_1>() , 4usize);
158158
}
159-
impl Clone for C__bindgen_ty_1_2 {
159+
impl Clone for C__bindgen_ty_1_1 {
160160
fn clone(&self) -> Self { *self }
161161
}
162162
#[test]

tests/expectations/struct_with_anon_struct_array.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,35 @@
77
#[repr(C)]
88
#[derive(Debug, Copy)]
99
pub struct foo {
10-
pub bar: [foo__bindgen_ty_1; 2usize],
11-
pub baz: [[[foo__bindgen_ty_2; 4usize]; 3usize]; 2usize],
10+
pub bar: [foo__bindgen_ty_2; 2usize],
11+
pub baz: [[[foo__bindgen_ty_1; 4usize]; 3usize]; 2usize],
1212
}
1313
#[repr(C)]
1414
#[derive(Debug, Copy)]
15-
pub struct foo__bindgen_ty_1 {
15+
pub struct foo__bindgen_ty_2 {
1616
pub a: ::std::os::raw::c_int,
1717
pub b: ::std::os::raw::c_int,
1818
}
1919
#[test]
20-
fn bindgen_test_layout_foo__bindgen_ty_1() {
21-
assert_eq!(::std::mem::size_of::<foo__bindgen_ty_1>() , 8usize);
22-
assert_eq!(::std::mem::align_of::<foo__bindgen_ty_1>() , 4usize);
20+
fn bindgen_test_layout_foo__bindgen_ty_2() {
21+
assert_eq!(::std::mem::size_of::<foo__bindgen_ty_2>() , 8usize);
22+
assert_eq!(::std::mem::align_of::<foo__bindgen_ty_2>() , 4usize);
2323
}
24-
impl Clone for foo__bindgen_ty_1 {
24+
impl Clone for foo__bindgen_ty_2 {
2525
fn clone(&self) -> Self { *self }
2626
}
2727
#[repr(C)]
2828
#[derive(Debug, Copy)]
29-
pub struct foo__bindgen_ty_2 {
29+
pub struct foo__bindgen_ty_1 {
3030
pub a: ::std::os::raw::c_int,
3131
pub b: ::std::os::raw::c_int,
3232
}
3333
#[test]
34-
fn bindgen_test_layout_foo__bindgen_ty_2() {
35-
assert_eq!(::std::mem::size_of::<foo__bindgen_ty_2>() , 8usize);
36-
assert_eq!(::std::mem::align_of::<foo__bindgen_ty_2>() , 4usize);
34+
fn bindgen_test_layout_foo__bindgen_ty_1() {
35+
assert_eq!(::std::mem::size_of::<foo__bindgen_ty_1>() , 8usize);
36+
assert_eq!(::std::mem::align_of::<foo__bindgen_ty_1>() , 4usize);
3737
}
38-
impl Clone for foo__bindgen_ty_2 {
38+
impl Clone for foo__bindgen_ty_1 {
3939
fn clone(&self) -> Self { *self }
4040
}
4141
#[test]

tests/expectations/struct_with_nesting.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,38 +34,38 @@ pub struct foo {
3434
#[derive(Debug, Copy)]
3535
pub struct foo__bindgen_ty_1 {
3636
pub b: __BindgenUnionField<::std::os::raw::c_uint>,
37-
pub __bindgen_anon_1: __BindgenUnionField<foo__bindgen_ty_1_1>,
38-
pub __bindgen_anon_2: __BindgenUnionField<foo__bindgen_ty_1_2>,
37+
pub __bindgen_anon_1: __BindgenUnionField<foo__bindgen_ty_1_2>,
38+
pub __bindgen_anon_2: __BindgenUnionField<foo__bindgen_ty_1_1>,
3939
pub bindgen_union_field: u32,
4040
}
4141
#[repr(C)]
4242
#[derive(Debug, Copy)]
43-
pub struct foo__bindgen_ty_1_1 {
43+
pub struct foo__bindgen_ty_1_2 {
4444
pub c1: ::std::os::raw::c_ushort,
4545
pub c2: ::std::os::raw::c_ushort,
4646
}
4747
#[test]
48-
fn bindgen_test_layout_foo__bindgen_ty_1_1() {
49-
assert_eq!(::std::mem::size_of::<foo__bindgen_ty_1_1>() , 4usize);
50-
assert_eq!(::std::mem::align_of::<foo__bindgen_ty_1_1>() , 2usize);
48+
fn bindgen_test_layout_foo__bindgen_ty_1_2() {
49+
assert_eq!(::std::mem::size_of::<foo__bindgen_ty_1_2>() , 4usize);
50+
assert_eq!(::std::mem::align_of::<foo__bindgen_ty_1_2>() , 2usize);
5151
}
52-
impl Clone for foo__bindgen_ty_1_1 {
52+
impl Clone for foo__bindgen_ty_1_2 {
5353
fn clone(&self) -> Self { *self }
5454
}
5555
#[repr(C)]
5656
#[derive(Debug, Copy)]
57-
pub struct foo__bindgen_ty_1_2 {
57+
pub struct foo__bindgen_ty_1_1 {
5858
pub d1: ::std::os::raw::c_uchar,
5959
pub d2: ::std::os::raw::c_uchar,
6060
pub d3: ::std::os::raw::c_uchar,
6161
pub d4: ::std::os::raw::c_uchar,
6262
}
6363
#[test]
64-
fn bindgen_test_layout_foo__bindgen_ty_1_2() {
65-
assert_eq!(::std::mem::size_of::<foo__bindgen_ty_1_2>() , 4usize);
66-
assert_eq!(::std::mem::align_of::<foo__bindgen_ty_1_2>() , 1usize);
64+
fn bindgen_test_layout_foo__bindgen_ty_1_1() {
65+
assert_eq!(::std::mem::size_of::<foo__bindgen_ty_1_1>() , 4usize);
66+
assert_eq!(::std::mem::align_of::<foo__bindgen_ty_1_1>() , 1usize);
6767
}
68-
impl Clone for foo__bindgen_ty_1_2 {
68+
impl Clone for foo__bindgen_ty_1_1 {
6969
fn clone(&self) -> Self { *self }
7070
}
7171
#[test]

tests/expectations/type_alias_empty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
#![allow(non_snake_case)]
55

66

7-
7+
pub type bool_constant = ();

tests/expectations/union_template.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,21 @@ impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
2828
#[derive(Debug, Copy, Clone)]
2929
pub struct NastyStruct<T> {
3030
pub mIsSome: bool,
31-
pub mStorage: NastyStruct__bindgen_ty_1<T>,
32-
pub __bindgen_anon_1: NastyStruct__bindgen_ty_2<T>,
31+
pub mStorage: NastyStruct__bindgen_ty_2<T>,
32+
pub __bindgen_anon_1: NastyStruct__bindgen_ty_1<T>,
3333
pub _phantom_0: ::std::marker::PhantomData<T>,
3434
}
3535
#[repr(C)]
3636
#[derive(Debug, Copy, Clone)]
37-
pub struct NastyStruct__bindgen_ty_1<T> {
37+
pub struct NastyStruct__bindgen_ty_2<T> {
3838
pub mFoo: __BindgenUnionField<*mut ::std::os::raw::c_void>,
3939
pub mDummy: __BindgenUnionField<::std::os::raw::c_ulong>,
4040
pub bindgen_union_field: u64,
4141
pub _phantom_0: ::std::marker::PhantomData<T>,
4242
}
4343
#[repr(C)]
4444
#[derive(Debug, Copy, Clone)]
45-
pub struct NastyStruct__bindgen_ty_2<T> {
45+
pub struct NastyStruct__bindgen_ty_1<T> {
4646
pub wat: __BindgenUnionField<::std::os::raw::c_short>,
4747
pub wut: __BindgenUnionField<*mut ::std::os::raw::c_int>,
4848
pub bindgen_union_field: u64,

0 commit comments

Comments
 (0)