@@ -13,6 +13,7 @@ use ir::item::{Item, ItemAncestors, ItemCanonicalName, ItemCanonicalPath};
13
13
use ir:: item_kind:: ItemKind ;
14
14
use ir:: layout:: Layout ;
15
15
use ir:: module:: Module ;
16
+ use ir:: objc:: ObjCInterface ;
16
17
use ir:: ty:: { Type , TypeKind } ;
17
18
use ir:: type_collector:: ItemSet ;
18
19
use ir:: var:: Var ;
@@ -87,6 +88,9 @@ struct CodegenResult<'a> {
87
88
/// Whether an incomplete array has been generated at least once.
88
89
saw_incomplete_array : bool ,
89
90
91
+ /// Whether Objective C types have been seen at least once.
92
+ saw_objc : bool ,
93
+
90
94
items_seen : HashSet < ItemId > ,
91
95
/// The set of generated function/var names, needed because in C/C++ is
92
96
/// legal to do something like:
@@ -119,6 +123,7 @@ impl<'a> CodegenResult<'a> {
119
123
items : vec ! [ ] ,
120
124
saw_union : false ,
121
125
saw_incomplete_array : false ,
126
+ saw_objc : false ,
122
127
codegen_id : codegen_id,
123
128
items_seen : Default :: default ( ) ,
124
129
functions_seen : Default :: default ( ) ,
@@ -140,6 +145,10 @@ impl<'a> CodegenResult<'a> {
140
145
self . saw_incomplete_array = true ;
141
146
}
142
147
148
+ fn saw_objc ( & mut self ) {
149
+ self . saw_objc = true ;
150
+ }
151
+
143
152
fn seen ( & self , item : ItemId ) -> bool {
144
153
self . items_seen . contains ( & item)
145
154
}
@@ -184,6 +193,7 @@ impl<'a> CodegenResult<'a> {
184
193
185
194
self . saw_union |= new. saw_union ;
186
195
self . saw_incomplete_array |= new. saw_incomplete_array ;
196
+ self . saw_objc |= new. saw_objc ;
187
197
188
198
new. items
189
199
}
@@ -359,6 +369,9 @@ impl CodeGenerator for Module {
359
369
if ctx. need_bindegen_complex_type ( ) {
360
370
utils:: prepend_complex_type ( ctx, & mut * result) ;
361
371
}
372
+ if result. saw_objc {
373
+ utils:: prepend_objc_header ( ctx, & mut * result) ;
374
+ }
362
375
}
363
376
} ;
364
377
@@ -514,7 +527,7 @@ impl CodeGenerator for Type {
514
527
TypeKind :: TemplateRef ( ..) |
515
528
TypeKind :: Function ( ..) |
516
529
TypeKind :: ResolvedTypeRef ( ..) |
517
- TypeKind :: Named ( .. ) => {
530
+ TypeKind :: Named => {
518
531
// These items don't need code generation, they only need to be
519
532
// converted to rust types in fields, arguments, and such.
520
533
return ;
@@ -524,8 +537,8 @@ impl CodeGenerator for Type {
524
537
}
525
538
// NB: The code below will pick the correct
526
539
// applicable_template_args.
527
- TypeKind :: TemplateAlias ( ref spelling , inner, _) |
528
- TypeKind :: Alias ( ref spelling , inner) => {
540
+ TypeKind :: TemplateAlias ( inner, _) |
541
+ TypeKind :: Alias ( inner) => {
529
542
let inner_item = ctx. resolve_item ( inner) ;
530
543
let name = item. canonical_name ( ctx) ;
531
544
@@ -541,6 +554,7 @@ impl CodeGenerator for Type {
541
554
542
555
// If this is a known named type, disallow generating anything
543
556
// for it too.
557
+ let spelling = self . name ( ) . expect ( "Unnamed alias?" ) ;
544
558
if utils:: type_from_named ( ctx, spelling, inner) . is_some ( ) {
545
559
return ;
546
560
}
@@ -556,6 +570,26 @@ impl CodeGenerator for Type {
556
570
inner_item. to_rust_ty ( ctx)
557
571
} ;
558
572
573
+ {
574
+ // FIXME(emilio): This is a workaround to avoid generating
575
+ // incorrect type aliases because of types that we haven't
576
+ // been able to resolve (because, eg, they depend on a
577
+ // template parameter).
578
+ //
579
+ // It's kind of a shame not generating them even when they
580
+ // could be referenced, but we already do the same for items
581
+ // with invalid template parameters, and at least this way
582
+ // they can be replaced, instead of generating plain invalid
583
+ // code.
584
+ let inner_canon_type =
585
+ inner_item. expect_type ( ) . canonical_type ( ctx) ;
586
+ if inner_canon_type. is_invalid_named_type ( ) {
587
+ warn ! ( "Item contained invalid named type, skipping: \
588
+ {:?}, {:?}", item, inner_item) ;
589
+ return ;
590
+ }
591
+ }
592
+
559
593
let rust_name = ctx. rust_ident ( & name) ;
560
594
let mut typedef = aster:: AstBuilder :: new ( ) . item ( ) . pub_ ( ) ;
561
595
@@ -593,9 +627,8 @@ impl CodeGenerator for Type {
593
627
for template_arg in applicable_template_args. iter ( ) {
594
628
let template_arg = ctx. resolve_type ( * template_arg) ;
595
629
if template_arg. is_named ( ) {
596
- let name = template_arg. name ( ) . unwrap ( ) ;
597
- if name. contains ( "typename " ) {
598
- warn ! ( "Item contained `typename`'d template \
630
+ if template_arg. is_invalid_named_type ( ) {
631
+ warn ! ( "Item contained invalid template \
599
632
parameter: {:?}", item) ;
600
633
return ;
601
634
}
@@ -610,6 +643,9 @@ impl CodeGenerator for Type {
610
643
TypeKind :: Enum ( ref ei) => {
611
644
ei. codegen ( ctx, result, whitelisted_items, item)
612
645
}
646
+ TypeKind :: ObjCInterface ( ref interface) => {
647
+ interface. codegen ( ctx, result, whitelisted_items, item)
648
+ }
613
649
ref u @ TypeKind :: UnresolvedTypeRef ( ..) => {
614
650
unreachable ! ( "Should have been resolved after parsing {:?}!" , u)
615
651
}
@@ -2040,14 +2076,15 @@ impl ToRustTy for Type {
2040
2076
P ( inner_ty)
2041
2077
}
2042
2078
TypeKind :: ResolvedTypeRef ( inner) => inner. to_rust_ty ( ctx) ,
2043
- TypeKind :: TemplateAlias ( ref spelling , inner, _) |
2044
- TypeKind :: Alias ( ref spelling , inner) => {
2079
+ TypeKind :: TemplateAlias ( inner, _) |
2080
+ TypeKind :: Alias ( inner) => {
2045
2081
let applicable_named_args =
2046
2082
item. applicable_template_args ( ctx)
2047
2083
. into_iter ( )
2048
2084
. filter ( |arg| ctx. resolve_type ( * arg) . is_named ( ) )
2049
2085
. collect :: < Vec < _ > > ( ) ;
2050
2086
2087
+ let spelling = self . name ( ) . expect ( "Unnamed alias?" ) ;
2051
2088
if item. is_opaque ( ctx) && !applicable_named_args. is_empty ( ) {
2052
2089
// Pray if there's no available layout.
2053
2090
let layout = self . layout ( ctx) . unwrap_or_else ( Layout :: zero) ;
@@ -2101,11 +2138,14 @@ impl ToRustTy for Type {
2101
2138
ty. to_ptr ( is_const, ctx. span ( ) )
2102
2139
}
2103
2140
}
2104
- TypeKind :: Named ( .. ) => {
2141
+ TypeKind :: Named => {
2105
2142
let name = item. canonical_name ( ctx) ;
2106
2143
let ident = ctx. rust_ident ( & name) ;
2107
2144
quote_ty ! ( ctx. ext_cx( ) , $ident)
2108
2145
}
2146
+ TypeKind :: ObjCInterface ( ..) => {
2147
+ quote_ty ! ( ctx. ext_cx( ) , id)
2148
+ } ,
2109
2149
ref u @ TypeKind :: UnresolvedTypeRef ( ..) => {
2110
2150
unreachable ! ( "Should have been resolved after parsing {:?}!" , u)
2111
2151
}
@@ -2139,10 +2179,22 @@ impl ToRustTy for FunctionSig {
2139
2179
// the array type derivation.
2140
2180
//
2141
2181
// [1]: http://c0x.coding-guidelines.com/6.7.5.3.html
2142
- let arg_ty = if let TypeKind :: Array ( t, _) = * arg_ty. canonical_type ( ctx) . kind ( ) {
2143
- t. to_rust_ty ( ctx) . to_ptr ( arg_ty. is_const ( ) , ctx. span ( ) )
2144
- } else {
2145
- arg_item. to_rust_ty ( ctx)
2182
+ let arg_ty = match * arg_ty. canonical_type ( ctx) . kind ( ) {
2183
+ TypeKind :: Array ( t, _) => {
2184
+ t. to_rust_ty ( ctx) . to_ptr ( arg_ty. is_const ( ) , ctx. span ( ) )
2185
+ } ,
2186
+ TypeKind :: Pointer ( inner) => {
2187
+ let inner = ctx. resolve_item ( inner) ;
2188
+ let inner_ty = inner. expect_type ( ) ;
2189
+ if let TypeKind :: ObjCInterface ( _) = * inner_ty. canonical_type ( ctx) . kind ( ) {
2190
+ quote_ty ! ( ctx. ext_cx( ) , id)
2191
+ } else {
2192
+ arg_item. to_rust_ty ( ctx)
2193
+ }
2194
+ } ,
2195
+ _ => {
2196
+ arg_item. to_rust_ty ( ctx)
2197
+ }
2146
2198
} ;
2147
2199
2148
2200
let arg_name = match * name {
@@ -2261,6 +2313,85 @@ impl CodeGenerator for Function {
2261
2313
}
2262
2314
}
2263
2315
2316
+ impl CodeGenerator for ObjCInterface {
2317
+ type Extra = Item ;
2318
+ fn codegen < ' a > ( & self ,
2319
+ ctx : & BindgenContext ,
2320
+ result : & mut CodegenResult < ' a > ,
2321
+ _whitelisted_items : & ItemSet ,
2322
+ _: & Item ) {
2323
+ let mut impl_items = vec ! [ ] ;
2324
+ let mut trait_items = vec ! [ ] ;
2325
+
2326
+ for method in self . methods ( ) {
2327
+ let method_name = ctx. rust_ident ( method. name ( ) ) ;
2328
+
2329
+ let body = quote_stmt ! ( ctx. ext_cx( ) , msg_send![ self , $method_name] )
2330
+ . unwrap ( ) ;
2331
+ let block = ast:: Block {
2332
+ stmts : vec ! [ body] ,
2333
+ id : ast:: DUMMY_NODE_ID ,
2334
+ rules : ast:: BlockCheckMode :: Default ,
2335
+ span : ctx. span ( ) ,
2336
+ } ;
2337
+
2338
+ let sig = aster:: AstBuilder :: new ( )
2339
+ . method_sig ( )
2340
+ . unsafe_ ( )
2341
+ . fn_decl ( )
2342
+ . self_ ( )
2343
+ . build ( ast:: SelfKind :: Value ( ast:: Mutability :: Immutable ) )
2344
+ . build ( ast:: FunctionRetTy :: Default ( ctx. span ( ) ) ) ;
2345
+ let attrs = vec ! [ ] ;
2346
+
2347
+ let impl_item = ast:: ImplItem {
2348
+ id : ast:: DUMMY_NODE_ID ,
2349
+ ident : ctx. rust_ident ( method. rust_name ( ) ) ,
2350
+ vis : ast:: Visibility :: Inherited , // Public,
2351
+ attrs : attrs. clone ( ) ,
2352
+ node : ast:: ImplItemKind :: Method ( sig. clone ( ) , P ( block) ) ,
2353
+ defaultness : ast:: Defaultness :: Final ,
2354
+ span : ctx. span ( ) ,
2355
+ } ;
2356
+
2357
+ let trait_item = ast:: TraitItem {
2358
+ id : ast:: DUMMY_NODE_ID ,
2359
+ ident : ctx. rust_ident ( method. rust_name ( ) ) ,
2360
+ attrs : attrs,
2361
+ node : ast:: TraitItemKind :: Method ( sig, None ) ,
2362
+ span : ctx. span ( ) ,
2363
+ } ;
2364
+
2365
+ impl_items. push ( impl_item) ;
2366
+ trait_items. push ( trait_item)
2367
+ }
2368
+
2369
+
2370
+ let trait_block = aster:: AstBuilder :: new ( )
2371
+ . item ( )
2372
+ . pub_ ( )
2373
+ . trait_ ( self . name ( ) )
2374
+ . with_items ( trait_items)
2375
+ . build ( ) ;
2376
+
2377
+ let ty_for_impl = quote_ty ! ( ctx. ext_cx( ) , id) ;
2378
+ let impl_block = aster:: AstBuilder :: new ( )
2379
+ . item ( )
2380
+ . impl_ ( )
2381
+ . trait_ ( )
2382
+ . id ( self . name ( ) )
2383
+ . build ( )
2384
+ . with_items ( impl_items)
2385
+ . build_ty ( ty_for_impl) ;
2386
+
2387
+ result. push ( trait_block) ;
2388
+ result. push ( impl_block) ;
2389
+ result. saw_objc ( ) ;
2390
+ }
2391
+ }
2392
+
2393
+
2394
+
2264
2395
pub fn codegen ( context : & mut BindgenContext ) -> Vec < P < ast:: Item > > {
2265
2396
context. gen ( |context| {
2266
2397
let counter = Cell :: new ( 0 ) ;
@@ -2294,6 +2425,32 @@ mod utils {
2294
2425
use syntax:: ast;
2295
2426
use syntax:: ptr:: P ;
2296
2427
2428
+
2429
+ pub fn prepend_objc_header ( ctx : & BindgenContext ,
2430
+ result : & mut Vec < P < ast:: Item > > ) {
2431
+ let use_objc = if ctx. options ( ) . objc_extern_crate {
2432
+ quote_item ! ( ctx. ext_cx( ) ,
2433
+ use objc;
2434
+ ) . unwrap ( )
2435
+ } else {
2436
+ quote_item ! ( ctx. ext_cx( ) ,
2437
+ #[ macro_use]
2438
+ extern crate objc;
2439
+ ) . unwrap ( )
2440
+ } ;
2441
+
2442
+
2443
+ let id_type = quote_item ! ( ctx. ext_cx( ) ,
2444
+ #[ allow( non_camel_case_types) ]
2445
+ pub type id = * mut objc:: runtime:: Object ;
2446
+ )
2447
+ . unwrap ( ) ;
2448
+
2449
+ let items = vec ! [ use_objc, id_type] ;
2450
+ let old_items = mem:: replace ( result, items) ;
2451
+ result. extend ( old_items. into_iter ( ) ) ;
2452
+ }
2453
+
2297
2454
pub fn prepend_union_types ( ctx : & BindgenContext ,
2298
2455
result : & mut Vec < P < ast:: Item > > ) {
2299
2456
let prefix = ctx. trait_prefix ( ) ;
0 commit comments