Skip to content

Commit 2d25a43

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 a5e9153 commit 2d25a43

7 files changed

+94
-147
lines changed

src/codegen/mod.rs

Lines changed: 29 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use ir::item_kind::ItemKind;
1414
use ir::comp::{CompKind, CompInfo, Field, Method};
1515
use ir::layout::Layout;
1616
use ir::annotations::FieldAccessorKind;
17-
use ir::type_collector::{ItemSet, TypeCollector};
17+
use ir::type_collector::ItemSet;
1818

1919
use std::ops;
2020
use std::borrow::Cow;
@@ -1584,97 +1584,44 @@ impl CodeGenerator for Function {
15841584
}
15851585
}
15861586

1587+
// Return true if any of the ancestors of `id` are in the whitelisted items set,
1588+
// false otherwise.
1589+
fn ancestor_is_whitelisted(ctx: &BindgenContext, whitelisted_items: &ItemSet, id: ItemId) -> bool {
1590+
let item = ctx.resolve_item(id);
1591+
let mut last = id;
1592+
let mut current = item.parent_id();
1593+
1594+
while last != current {
1595+
if whitelisted_items.contains(&current) {
1596+
return true;
1597+
}
1598+
last = current;
1599+
current = ctx.resolve_item(current).parent_id();
1600+
}
1601+
1602+
false
1603+
}
1604+
15871605
pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
15881606
context.gen(|context| {
15891607
let mut result = CodegenResult::new();
15901608

15911609
debug!("codegen: {:?}", context.options());
15921610

1593-
// If the whitelisted types and functions sets are empty, just generate
1594-
// everything.
1595-
if context.options().whitelisted_types.is_empty() &&
1596-
context.options().whitelisted_functions.is_empty() &&
1597-
context.options().whitelisted_vars.is_empty() {
1598-
for (_item_id, item) in context.items() {
1599-
// Non-toplevel item parents are the responsible one for generating
1600-
// them.
1601-
if item.is_toplevel(context) {
1602-
item.codegen(context, &mut result, &());
1603-
}
1604-
}
1605-
} else {
1606-
// Recursively collect all the types dependent on the whitelisted
1607-
// types, then generate them.
1608-
//
1609-
// FIXME(emilio): This pass is probably slow, but it can't be faster
1610-
// than docopt anyway :)
1611-
let mut items = ItemSet::new();
1612-
for (_item_id, item) in context.items() {
1613-
// FIXME(emilio): This probably should look only at whether the
1614-
// parent is a module.
1615-
if !item.is_toplevel(context) {
1616-
continue;
1617-
}
1611+
let whitelisted_items: ItemSet = context.whitelisted_items().collect();
16181612

1619-
let name = item.canonical_name(context);
1620-
match *item.kind() {
1621-
ItemKind::Type(ref ty) => {
1622-
if context.options().whitelisted_types.matches(&name) {
1623-
item.collect_types(context, &mut items, &());
1624-
}
1625-
// Unnamed top-level enums are special and we whitelist
1626-
// them via the whitelisted_vars filter, since they're
1627-
// effectively top-level constants, and there's no way
1628-
// for them to be referenced consistently.
1629-
if let TypeKind::Enum(ref enum_) = *ty.kind() {
1630-
if ty.name().is_none() {
1631-
if enum_.variants().iter().any(|variant| {
1632-
context.options().whitelisted_vars.matches(&variant.name())
1633-
}) {
1634-
item.collect_types(context, &mut items, &());
1635-
}
1636-
}
1637-
}
1638-
}
1639-
ItemKind::Function(ref fun) => {
1640-
if context.options().whitelisted_functions.matches(&name) {
1641-
items.insert(item.id());
1642-
fun.signature().collect_types(context, &mut items, &());
1643-
}
1644-
}
1645-
ItemKind::Var(ref var) => {
1646-
if context.options().whitelisted_vars.matches(&name) {
1647-
items.insert(item.id());
1648-
var.ty().collect_types(context, &mut items, &());
1649-
}
1650-
}
1651-
ItemKind::Module(..) => {}
1652-
}
1653-
}
1654-
1655-
fn contains_parent(ctx: &BindgenContext, types: &ItemSet, id: ItemId) -> bool {
1656-
let item = ctx.resolve_item(id);
1657-
let mut last = id;
1658-
let mut current = item.parent_id();
1613+
for &id in whitelisted_items.iter() {
1614+
let item = context.resolve_item(id);
16591615

1660-
while last != current {
1661-
if types.contains(&current) {
1662-
return true;
1663-
}
1664-
last = current;
1665-
current = ctx.resolve_item(current).parent_id();
1666-
}
1667-
1668-
false
1669-
}
1670-
1671-
for item_id in items.iter() {
1672-
let item = context.resolve_item(*item_id);
1673-
if item.is_toplevel(context) || !contains_parent(context, &items, *item_id) {
1674-
item.codegen(context, &mut result, &());
1675-
}
1616+
// Non-toplevel items' parents are responsible one for generating
1617+
// their children. However, if we find an orphaned reference to a
1618+
// non-toplevel item whose parent is not in our whitelisted set, we
1619+
// need to take responsibility for generating it.
1620+
if item.is_toplevel(context) || !ancestor_is_whitelisted(context, &whitelisted_items, id) {
1621+
item.codegen(context, &mut result, &());
16761622
}
16771623
}
1624+
16781625
let saw_union = result.saw_union;
16791626
let mut result = result.items;
16801627
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)