@@ -14,7 +14,7 @@ use ir::item_kind::ItemKind;
14
14
use ir:: layout:: Layout ;
15
15
use ir:: module:: Module ;
16
16
use ir:: ty:: { Type , TypeKind } ;
17
- use ir:: type_collector:: { ItemSet , TypeCollector } ;
17
+ use ir:: type_collector:: ItemSet ;
18
18
use ir:: var:: Var ;
19
19
use self :: helpers:: { BlobTyBuilder , attributes} ;
20
20
@@ -1692,108 +1692,48 @@ impl CodeGenerator for Function {
1692
1692
}
1693
1693
}
1694
1694
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
+
1695
1716
pub fn codegen ( context : & mut BindgenContext ) -> Vec < P < ast:: Item > > {
1696
1717
context. gen ( |context| {
1697
1718
let mut result = CodegenResult :: new ( ) ;
1698
1719
1699
1720
debug ! ( "codegen: {:?}" , context. options( ) ) ;
1700
1721
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 ( ) ;
1785
1723
1786
- false
1787
- }
1724
+ for & id in whitelisted_items . iter ( ) {
1725
+ let item = context . resolve_item ( id ) ;
1788
1726
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, & ( ) ) ;
1795
1734
}
1796
1735
}
1736
+
1797
1737
let saw_union = result. saw_union ;
1798
1738
let mut result = result. items ;
1799
1739
if saw_union && !context. options ( ) . unstable_rust {
0 commit comments