@@ -14,6 +14,18 @@ use syntax::ext::base::ExtCtxt;
14
14
use parse:: ClangItemParser ;
15
15
use BindgenOptions ;
16
16
17
+ /// A key used to index a resolved type, so we only process it once.
18
+ ///
19
+ /// This is almost always a USR string (an unique identifier generated by
20
+ /// clang), but it can also be the canonical declaration if the type is unnamed,
21
+ /// in which case clang may generate the same USR for multiple nested unnamed
22
+ /// types.
23
+ #[ derive( Eq , PartialEq , Hash , Debug ) ]
24
+ enum TypeKey {
25
+ USR ( String ) ,
26
+ Declaration ( Cursor ) ,
27
+ }
28
+
17
29
// This is just convenience to avoid creating a manual debug impl for the
18
30
// context.
19
31
struct GenContext < ' ctx > ( ExtCtxt < ' ctx > ) ;
@@ -33,11 +45,9 @@ pub struct BindgenContext<'ctx> {
33
45
/// output.
34
46
items : BTreeMap < ItemId , Item > ,
35
47
36
- /// Clang cursor to type map. This is needed to be able to associate types
37
- /// with item ids during parsing.
38
- ///
39
- /// The cursor used for storage is the definition cursor.
40
- types : HashMap < Cursor , ItemId > ,
48
+ /// Clang USR to type map. This is needed to be able to associate types with
49
+ /// item ids during parsing.
50
+ types : HashMap < TypeKey , ItemId > ,
41
51
42
52
/// A cursor to module map. Similar reason than above.
43
53
modules : HashMap < Cursor , ItemId > ,
@@ -131,29 +141,46 @@ impl<'ctx> BindgenContext<'ctx> {
131
141
132
142
let id = item. id ( ) ;
133
143
let is_type = item. kind ( ) . is_type ( ) ;
144
+ let is_unnamed = is_type && item. expect_type ( ) . name ( ) . is_none ( ) ;
134
145
let old_item = self . items . insert ( id, item) ;
135
146
assert ! ( old_item. is_none( ) , "Inserted type twice?" ) ;
136
147
148
+ // Unnamed items can have an USR, but they can't be referenced from
149
+ // other sites explicitly and the USR can match if the unnamed items are
150
+ // nested, so don't bother tracking them.
137
151
if is_type && declaration. is_some ( ) {
138
- let declaration = declaration. unwrap ( ) ;
139
- debug_assert_eq ! ( declaration, declaration . canonical ( ) ) ;
140
- if declaration . is_valid ( ) {
141
- let old = self . types . insert ( declaration , id ) ;
142
- debug_assert_eq ! ( old , None ) ;
143
- } else if location . is_some ( ) &&
144
- ( location . unwrap ( ) . kind ( ) == CXCursor_ClassTemplate ||
145
- location . unwrap ( ) . kind ( ) == CXCursor_ClassTemplatePartialSpecialization ) {
146
- let old = self . types . insert ( location . unwrap ( ) . canonical ( ) , id ) ;
147
- debug_assert_eq ! ( old , None ) ;
148
- } else {
152
+ let mut declaration = declaration. unwrap ( ) ;
153
+ if ! declaration. is_valid ( ) {
154
+ if let Some ( location ) = location {
155
+ if location . kind ( ) == CXCursor_ClassTemplate ||
156
+ location . kind ( ) == CXCursor_ClassTemplatePartialSpecialization {
157
+ declaration = location ;
158
+ }
159
+ }
160
+ }
161
+ declaration = declaration . canonical ( ) ;
162
+ if !declaration . is_valid ( ) {
149
163
// This could happen, for example, with types like `int*` or
150
164
// similar.
151
165
//
152
166
// Fortunately, we don't care about those types being
153
167
// duplicated, so we can just ignore them.
154
168
debug ! ( "Invalid declaration {:?} found for type {:?}" ,
155
169
declaration, self . items. get( & id) . unwrap( ) . kind( ) . expect_type( ) ) ;
170
+ return ;
156
171
}
172
+
173
+ let key = if is_unnamed {
174
+ TypeKey :: Declaration ( declaration)
175
+ } else if let Some ( usr) = declaration. usr ( ) {
176
+ TypeKey :: USR ( usr)
177
+ } else {
178
+ error ! ( "Valid declaration with no USR: {:?}, {:?}" , declaration, location) ;
179
+ return ;
180
+ } ;
181
+
182
+ let old = self . types . insert ( key, id) ;
183
+ debug_assert_eq ! ( old, None ) ;
157
184
}
158
185
}
159
186
@@ -206,7 +233,7 @@ impl<'ctx> BindgenContext<'ctx> {
206
233
self . collected_typerefs
207
234
}
208
235
209
- fn collect_typerefs ( & mut self ) -> Vec < ( ItemId , clang:: Type , Option < clang:: Cursor > ) > {
236
+ fn collect_typerefs ( & mut self ) -> Vec < ( ItemId , clang:: Type , Option < clang:: Cursor > , Option < ItemId > ) > {
210
237
debug_assert ! ( !self . collected_typerefs) ;
211
238
self . collected_typerefs = true ;
212
239
let mut typerefs = vec ! [ ] ;
@@ -218,8 +245,8 @@ impl<'ctx> BindgenContext<'ctx> {
218
245
} ;
219
246
220
247
match * ty. kind ( ) {
221
- TypeKind :: UnresolvedTypeRef ( ref ty, loc) => {
222
- typerefs. push ( ( * id, ty. clone ( ) , loc) ) ;
248
+ TypeKind :: UnresolvedTypeRef ( ref ty, loc, parent_id ) => {
249
+ typerefs. push ( ( * id, ty. clone ( ) , loc, parent_id ) ) ;
223
250
}
224
251
_ => { } ,
225
252
} ;
@@ -230,9 +257,9 @@ impl<'ctx> BindgenContext<'ctx> {
230
257
fn resolve_typerefs ( & mut self ) {
231
258
let typerefs = self . collect_typerefs ( ) ;
232
259
233
- for ( id, ty, loc) in typerefs {
260
+ for ( id, ty, loc, parent_id ) in typerefs {
234
261
let _resolved = {
235
- let resolved = Item :: from_ty ( & ty, loc, None , self )
262
+ let resolved = Item :: from_ty ( & ty, loc, parent_id , self )
236
263
. expect ( "What happened?" ) ;
237
264
let mut item = self . items . get_mut ( & id) . unwrap ( ) ;
238
265
@@ -494,8 +521,15 @@ impl<'ctx> BindgenContext<'ctx> {
494
521
}
495
522
let canonical_declaration = declaration. canonical ( ) ;
496
523
if canonical_declaration. is_valid ( ) {
497
- // First lookup to see if we already have it resolved.
498
- let id = self . types . get ( & canonical_declaration) . map ( |id| * id) ;
524
+ let id =
525
+ self . types . get ( & TypeKey :: Declaration ( canonical_declaration) )
526
+ . map ( |id| * id)
527
+ . or_else ( || {
528
+ canonical_declaration. usr ( ) . and_then ( |usr| {
529
+ self . types . get ( & TypeKey :: USR ( usr) )
530
+ } )
531
+ . map ( |id| * id)
532
+ } ) ;
499
533
if let Some ( id) = id {
500
534
debug ! ( "Already resolved ty {:?}, {:?}, {:?} {:?}" ,
501
535
id, declaration, ty, location) ;
@@ -572,6 +606,8 @@ impl<'ctx> BindgenContext<'ctx> {
572
606
CXType_ULong => TypeKind :: Int ( IntKind :: ULong ) ,
573
607
CXType_LongLong => TypeKind :: Int ( IntKind :: LongLong ) ,
574
608
CXType_ULongLong => TypeKind :: Int ( IntKind :: ULongLong ) ,
609
+ CXType_Int128 => TypeKind :: Int ( IntKind :: I128 ) ,
610
+ CXType_UInt128 => TypeKind :: Int ( IntKind :: U128 ) ,
575
611
CXType_Float => TypeKind :: Float ( FloatKind :: Float ) ,
576
612
CXType_Double => TypeKind :: Float ( FloatKind :: Double ) ,
577
613
CXType_LongDouble => TypeKind :: Float ( FloatKind :: LongDouble ) ,
0 commit comments