1 //! Everything related to types in our intermediate representation.
2 
3 use super::comp::CompInfo;
4 use super::context::{BindgenContext, ItemId, TypeId};
5 use super::dot::DotAttributes;
6 use super::enum_ty::Enum;
7 use super::function::FunctionSig;
8 use super::int::IntKind;
9 use super::item::{IsOpaque, Item};
10 use super::layout::{Layout, Opaque};
11 use super::objc::ObjCInterface;
12 use super::template::{AsTemplateParam, TemplateInstantiation,
13                       TemplateParameters};
14 use super::traversal::{EdgeKind, Trace, Tracer};
15 use clang::{self, Cursor};
16 use parse::{ClangItemParser, ParseError, ParseResult};
17 use std::borrow::Cow;
18 use std::io;
19 
20 /// The base representation of a type in bindgen.
21 ///
22 /// A type has an optional name, which if present cannot be empty, a `layout`
23 /// (size, alignment and packedness) if known, a `Kind`, which determines which
24 /// kind of type it is, and whether the type is const.
25 #[derive(Debug)]
26 pub struct Type {
27     /// The name of the type, or None if it was an unnamed struct or union.
28     name: Option<String>,
29     /// The layout of the type, if known.
30     layout: Option<Layout>,
31     /// The inner kind of the type
32     kind: TypeKind,
33     /// Whether this type is const-qualified.
34     is_const: bool,
35 }
36 
37 /// The maximum number of items in an array for which Rust implements common
38 /// traits, and so if we have a type containing an array with more than this
39 /// many items, we won't be able to derive common traits on that type.
40 ///
41 /// We need type-level integers yesterday :'(
42 pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
43 
44 impl Type {
45     /// Get the underlying `CompInfo` for this type, or `None` if this is some
46     /// other kind of type.
as_comp(&self) -> Option<&CompInfo>47     pub fn as_comp(&self) -> Option<&CompInfo> {
48         match self.kind {
49             TypeKind::Comp(ref ci) => Some(ci),
50             _ => None,
51         }
52     }
53 
54     /// Get the underlying `CompInfo` for this type as a mutable reference, or
55     /// `None` if this is some other kind of type.
as_comp_mut(&mut self) -> Option<&mut CompInfo>56     pub fn as_comp_mut(&mut self) -> Option<&mut CompInfo> {
57         match self.kind {
58             TypeKind::Comp(ref mut ci) => Some(ci),
59             _ => None,
60         }
61     }
62 
63     /// Construct a new `Type`.
new( name: Option<String>, layout: Option<Layout>, kind: TypeKind, is_const: bool, ) -> Self64     pub fn new(
65         name: Option<String>,
66         layout: Option<Layout>,
67         kind: TypeKind,
68         is_const: bool,
69     ) -> Self {
70         Type {
71             name,
72             layout,
73             kind,
74             is_const,
75         }
76     }
77 
78     /// Which kind of type is this?
kind(&self) -> &TypeKind79     pub fn kind(&self) -> &TypeKind {
80         &self.kind
81     }
82 
83     /// Get a mutable reference to this type's kind.
kind_mut(&mut self) -> &mut TypeKind84     pub fn kind_mut(&mut self) -> &mut TypeKind {
85         &mut self.kind
86     }
87 
88     /// Get this type's name.
name(&self) -> Option<&str>89     pub fn name(&self) -> Option<&str> {
90         self.name.as_ref().map(|name| &**name)
91     }
92 
93     /// Whether this is a block pointer type.
is_block_pointer(&self) -> bool94     pub fn is_block_pointer(&self) -> bool {
95         match self.kind {
96             TypeKind::BlockPointer(..) => true,
97             _ => false,
98         }
99     }
100 
101     /// Is this a compound type?
is_comp(&self) -> bool102     pub fn is_comp(&self) -> bool {
103         match self.kind {
104             TypeKind::Comp(..) => true,
105             _ => false,
106         }
107     }
108 
109     /// Is this a union?
is_union(&self) -> bool110     pub fn is_union(&self) -> bool {
111         match self.kind {
112             TypeKind::Comp(ref comp) => comp.is_union(),
113             _ => false,
114         }
115     }
116 
117     /// Is this type of kind `TypeKind::TypeParam`?
is_type_param(&self) -> bool118     pub fn is_type_param(&self) -> bool {
119         match self.kind {
120             TypeKind::TypeParam => true,
121             _ => false,
122         }
123     }
124 
125     /// Is this a template instantiation type?
is_template_instantiation(&self) -> bool126     pub fn is_template_instantiation(&self) -> bool {
127         match self.kind {
128             TypeKind::TemplateInstantiation(..) => true,
129             _ => false,
130         }
131     }
132 
133     /// Is this a template alias type?
is_template_alias(&self) -> bool134     pub fn is_template_alias(&self) -> bool {
135         match self.kind {
136             TypeKind::TemplateAlias(..) => true,
137             _ => false,
138         }
139     }
140 
141     /// Is this a function type?
is_function(&self) -> bool142     pub fn is_function(&self) -> bool {
143         match self.kind {
144             TypeKind::Function(..) => true,
145             _ => false,
146         }
147     }
148 
149     /// Is this an enum type?
is_enum(&self) -> bool150     pub fn is_enum(&self) -> bool {
151         match self.kind {
152             TypeKind::Enum(..) => true,
153             _ => false,
154         }
155     }
156 
157     /// Is this either a builtin or named type?
is_builtin_or_type_param(&self) -> bool158     pub fn is_builtin_or_type_param(&self) -> bool {
159         match self.kind {
160             TypeKind::Void |
161             TypeKind::NullPtr |
162             TypeKind::Function(..) |
163             TypeKind::Array(..) |
164             TypeKind::Reference(..) |
165             TypeKind::Pointer(..) |
166             TypeKind::Int(..) |
167             TypeKind::Float(..) |
168             TypeKind::TypeParam => true,
169             _ => false,
170         }
171     }
172 
173     /// Creates a new named type, with name `name`.
named(name: String) -> Self174     pub fn named(name: String) -> Self {
175         let name = if name.is_empty() { None } else { Some(name) };
176         Self::new(name, None, TypeKind::TypeParam, false)
177     }
178 
179     /// Is this a floating point type?
is_float(&self) -> bool180     pub fn is_float(&self) -> bool {
181         match self.kind {
182             TypeKind::Float(..) => true,
183             _ => false,
184         }
185     }
186 
187     /// Is this a boolean type?
is_bool(&self) -> bool188     pub fn is_bool(&self) -> bool {
189         match self.kind {
190             TypeKind::Int(IntKind::Bool) => true,
191             _ => false,
192         }
193     }
194 
195     /// Is this an integer type?
is_integer(&self) -> bool196     pub fn is_integer(&self) -> bool {
197         match self.kind {
198             TypeKind::Int(..) => true,
199             _ => false,
200         }
201     }
202 
203     /// Cast this type to an integer kind, or `None` if it is not an integer
204     /// type.
as_integer(&self) -> Option<IntKind>205     pub fn as_integer(&self) -> Option<IntKind> {
206         match self.kind {
207             TypeKind::Int(int_kind) => Some(int_kind),
208             _ => None,
209         }
210     }
211 
212     /// Is this a `const` qualified type?
is_const(&self) -> bool213     pub fn is_const(&self) -> bool {
214         self.is_const
215     }
216 
217     /// Is this a reference to another type?
is_type_ref(&self) -> bool218     pub fn is_type_ref(&self) -> bool {
219         match self.kind {
220             TypeKind::ResolvedTypeRef(_) |
221             TypeKind::UnresolvedTypeRef(_, _, _) => true,
222             _ => false,
223         }
224     }
225 
226     /// Is this an unresolved reference?
is_unresolved_ref(&self) -> bool227     pub fn is_unresolved_ref(&self) -> bool {
228         match self.kind {
229             TypeKind::UnresolvedTypeRef(_, _, _) => true,
230             _ => false,
231         }
232     }
233 
234     /// Is this a incomplete array type?
is_incomplete_array(&self, ctx: &BindgenContext) -> Option<ItemId>235     pub fn is_incomplete_array(&self, ctx: &BindgenContext) -> Option<ItemId> {
236         match self.kind {
237             TypeKind::Array(item, len) => {
238                 if len == 0 { Some(item.into()) } else { None }
239             }
240             TypeKind::ResolvedTypeRef(inner) => {
241                 ctx.resolve_type(inner).is_incomplete_array(ctx)
242             }
243             _ => None,
244         }
245     }
246 
247     /// What is the layout of this type?
layout(&self, ctx: &BindgenContext) -> Option<Layout>248     pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
249         self.layout.or_else(|| {
250             match self.kind {
251                 TypeKind::Comp(ref ci) => ci.layout(ctx),
252                 // FIXME(emilio): This is a hack for anonymous union templates.
253                 // Use the actual pointer size!
254                 TypeKind::Pointer(..) => {
255                     Some(Layout::new(
256                         ctx.target_pointer_size(),
257                         ctx.target_pointer_size(),
258                     ))
259                 }
260                 TypeKind::ResolvedTypeRef(inner) => {
261                     ctx.resolve_type(inner).layout(ctx)
262                 }
263                 _ => None,
264             }
265         })
266     }
267 
268     /// Whether this named type is an invalid C++ identifier. This is done to
269     /// avoid generating invalid code with some cases we can't handle, see:
270     ///
271     /// tests/headers/381-decltype-alias.hpp
is_invalid_type_param(&self) -> bool272     pub fn is_invalid_type_param(&self) -> bool {
273         match self.kind {
274             TypeKind::TypeParam => {
275                 let name = self.name().expect("Unnamed named type?");
276                 !clang::is_valid_identifier(&name)
277             }
278             _ => false,
279         }
280     }
281 
282     /// Takes `name`, and returns a suitable identifier representation for it.
sanitize_name<'a>(name: &'a str) -> Cow<'a, str>283     fn sanitize_name<'a>(name: &'a str) -> Cow<'a, str> {
284         if clang::is_valid_identifier(name) {
285             return Cow::Borrowed(name);
286         }
287 
288         let name = name.replace(|c| c == ' ' || c == ':' || c == '.', "_");
289         Cow::Owned(name)
290     }
291 
292     /// Get this type's santizied name.
sanitized_name<'a>( &'a self, ctx: &BindgenContext, ) -> Option<Cow<'a, str>>293     pub fn sanitized_name<'a>(
294         &'a self,
295         ctx: &BindgenContext,
296     ) -> Option<Cow<'a, str>> {
297         let name_info = match *self.kind() {
298             TypeKind::Pointer(inner) => Some((inner.into(), Cow::Borrowed("ptr"))),
299             TypeKind::Reference(inner) => Some((inner.into(), Cow::Borrowed("ref"))),
300             TypeKind::Array(inner, length) => {
301                 Some((inner, format!("array{}", length).into()))
302             }
303             _ => None,
304         };
305         if let Some((inner, prefix)) = name_info {
306             ctx.resolve_item(inner)
307                 .expect_type()
308                 .sanitized_name(ctx)
309                 .map(|name| format!("{}_{}", prefix, name).into())
310         } else {
311             self.name().map(Self::sanitize_name)
312         }
313     }
314 
315     /// See safe_canonical_type.
canonical_type<'tr>( &'tr self, ctx: &'tr BindgenContext, ) -> &'tr Type316     pub fn canonical_type<'tr>(
317         &'tr self,
318         ctx: &'tr BindgenContext,
319     ) -> &'tr Type {
320         self.safe_canonical_type(ctx).expect(
321             "Should have been resolved after parsing!",
322         )
323     }
324 
325     /// Returns the canonical type of this type, that is, the "inner type".
326     ///
327     /// For example, for a `typedef`, the canonical type would be the
328     /// `typedef`ed type, for a template instantiation, would be the template
329     /// its specializing, and so on. Return None if the type is unresolved.
safe_canonical_type<'tr>( &'tr self, ctx: &'tr BindgenContext, ) -> Option<&'tr Type>330     pub fn safe_canonical_type<'tr>(
331         &'tr self,
332         ctx: &'tr BindgenContext,
333     ) -> Option<&'tr Type> {
334         match self.kind {
335             TypeKind::TypeParam |
336             TypeKind::Array(..) |
337             TypeKind::Vector(..) |
338             TypeKind::Comp(..) |
339             TypeKind::Opaque |
340             TypeKind::Int(..) |
341             TypeKind::Float(..) |
342             TypeKind::Complex(..) |
343             TypeKind::Function(..) |
344             TypeKind::Enum(..) |
345             TypeKind::Reference(..) |
346             TypeKind::Void |
347             TypeKind::NullPtr |
348             TypeKind::Pointer(..) |
349             TypeKind::ObjCId |
350             TypeKind::ObjCSel |
351             TypeKind::ObjCInterface(..) => Some(self),
352 
353             TypeKind::ResolvedTypeRef(inner) |
354             TypeKind::Alias(inner) |
355             TypeKind::BlockPointer(inner) |
356             TypeKind::TemplateAlias(inner, _) => {
357                 ctx.resolve_type(inner).safe_canonical_type(ctx)
358             }
359             TypeKind::TemplateInstantiation(ref inst) => {
360                 ctx.resolve_type(inst.template_definition())
361                     .safe_canonical_type(ctx)
362             }
363 
364             TypeKind::UnresolvedTypeRef(..) => None,
365         }
366     }
367 
368     /// There are some types we don't want to stop at when finding an opaque
369     /// item, so we can arrive to the proper item that needs to be generated.
should_be_traced_unconditionally(&self) -> bool370     pub fn should_be_traced_unconditionally(&self) -> bool {
371         match self.kind {
372             TypeKind::Comp(..) |
373             TypeKind::Function(..) |
374             TypeKind::Pointer(..) |
375             TypeKind::Array(..) |
376             TypeKind::Reference(..) |
377             TypeKind::TemplateInstantiation(..) |
378             TypeKind::ResolvedTypeRef(..) => true,
379             _ => false,
380         }
381     }
382 }
383 
384 impl IsOpaque for Type {
385     type Extra = Item;
386 
is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool387     fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool {
388         match self.kind {
389             TypeKind::Opaque => true,
390             TypeKind::TemplateInstantiation(ref inst) => {
391                 inst.is_opaque(ctx, item)
392             }
393             TypeKind::Comp(ref comp) => comp.is_opaque(ctx, &self.layout),
394             TypeKind::ResolvedTypeRef(to) => to.is_opaque(ctx, &()),
395             _ => false,
396         }
397     }
398 }
399 
400 impl AsTemplateParam for Type {
401     type Extra = Item;
402 
as_template_param( &self, ctx: &BindgenContext, item: &Item, ) -> Option<TypeId>403     fn as_template_param(
404         &self,
405         ctx: &BindgenContext,
406         item: &Item,
407     ) -> Option<TypeId> {
408         self.kind.as_template_param(ctx, item)
409     }
410 }
411 
412 impl AsTemplateParam for TypeKind {
413     type Extra = Item;
414 
as_template_param( &self, ctx: &BindgenContext, item: &Item, ) -> Option<TypeId>415     fn as_template_param(
416         &self,
417         ctx: &BindgenContext,
418         item: &Item,
419     ) -> Option<TypeId> {
420         match *self {
421             TypeKind::TypeParam => Some(item.id().expect_type_id(ctx)),
422             TypeKind::ResolvedTypeRef(id) => id.as_template_param(ctx, &()),
423             _ => None,
424         }
425     }
426 }
427 
428 impl DotAttributes for Type {
dot_attributes<W>( &self, ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,429     fn dot_attributes<W>(
430         &self,
431         ctx: &BindgenContext,
432         out: &mut W,
433     ) -> io::Result<()>
434     where
435         W: io::Write,
436     {
437         if let Some(ref layout) = self.layout {
438             writeln!(
439                 out,
440                 "<tr><td>size</td><td>{}</td></tr>
441                            <tr><td>align</td><td>{}</td></tr>",
442                 layout.size,
443                 layout.align
444             )?;
445             if layout.packed {
446                 writeln!(out, "<tr><td>packed</td><td>true</td></tr>")?;
447             }
448         }
449 
450         if self.is_const {
451             writeln!(out, "<tr><td>const</td><td>true</td></tr>")?;
452         }
453 
454         self.kind.dot_attributes(ctx, out)
455     }
456 }
457 
458 impl DotAttributes for TypeKind {
dot_attributes<W>( &self, ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,459     fn dot_attributes<W>(
460         &self,
461         ctx: &BindgenContext,
462         out: &mut W,
463     ) -> io::Result<()>
464     where
465         W: io::Write,
466     {
467         writeln!(out, "<tr><td>type kind</td><td>{}</td></tr>", self.kind_name())?;
468 
469         if let TypeKind::Comp(ref comp) = *self {
470             comp.dot_attributes(ctx, out)?;
471         }
472 
473         Ok(())
474     }
475 }
476 
477 impl TypeKind {
kind_name(&self) -> &'static str478     fn kind_name(&self) -> &'static str {
479         match *self {
480             TypeKind::Void => "Void",
481             TypeKind::NullPtr => "NullPtr",
482             TypeKind::Comp(..) => "Comp",
483             TypeKind::Opaque => "Opaque",
484             TypeKind::Int(..) => "Int",
485             TypeKind::Float(..) => "Float",
486             TypeKind::Complex(..) => "Complex",
487             TypeKind::Alias(..) => "Alias",
488             TypeKind::TemplateAlias(..) => "TemplateAlias",
489             TypeKind::Array(..) => "Array",
490             TypeKind::Vector(..) => "Vector",
491             TypeKind::Function(..) => "Function",
492             TypeKind::Enum(..) => "Enum",
493             TypeKind::Pointer(..) => "Pointer",
494             TypeKind::BlockPointer(..) => "BlockPointer",
495             TypeKind::Reference(..) => "Reference",
496             TypeKind::TemplateInstantiation(..) => "TemplateInstantiation",
497             TypeKind::UnresolvedTypeRef(..) => "UnresolvedTypeRef",
498             TypeKind::ResolvedTypeRef(..) => "ResolvedTypeRef",
499             TypeKind::TypeParam => "TypeParam",
500             TypeKind::ObjCInterface(..) => "ObjCInterface",
501             TypeKind::ObjCId => "ObjCId",
502             TypeKind::ObjCSel => "ObjCSel",
503         }
504     }
505 }
506 
507 #[test]
is_invalid_type_param_valid()508 fn is_invalid_type_param_valid() {
509     let ty = Type::new(Some("foo".into()), None, TypeKind::TypeParam, false);
510     assert!(!ty.is_invalid_type_param())
511 }
512 
513 #[test]
is_invalid_type_param_valid_underscore_and_numbers()514 fn is_invalid_type_param_valid_underscore_and_numbers() {
515     let ty = Type::new(
516         Some("_foo123456789_".into()),
517         None,
518         TypeKind::TypeParam,
519         false,
520     );
521     assert!(!ty.is_invalid_type_param())
522 }
523 
524 #[test]
is_invalid_type_param_valid_unnamed_kind()525 fn is_invalid_type_param_valid_unnamed_kind() {
526     let ty = Type::new(Some("foo".into()), None, TypeKind::Void, false);
527     assert!(!ty.is_invalid_type_param())
528 }
529 
530 #[test]
is_invalid_type_param_invalid_start()531 fn is_invalid_type_param_invalid_start() {
532     let ty = Type::new(Some("1foo".into()), None, TypeKind::TypeParam, false);
533     assert!(ty.is_invalid_type_param())
534 }
535 
536 #[test]
is_invalid_type_param_invalid_remaing()537 fn is_invalid_type_param_invalid_remaing() {
538     let ty = Type::new(Some("foo-".into()), None, TypeKind::TypeParam, false);
539     assert!(ty.is_invalid_type_param())
540 }
541 
542 #[test]
543 #[should_panic]
is_invalid_type_param_unnamed()544 fn is_invalid_type_param_unnamed() {
545     let ty = Type::new(None, None, TypeKind::TypeParam, false);
546     assert!(ty.is_invalid_type_param())
547 }
548 
549 #[test]
is_invalid_type_param_empty_name()550 fn is_invalid_type_param_empty_name() {
551     let ty = Type::new(Some("".into()), None, TypeKind::TypeParam, false);
552     assert!(ty.is_invalid_type_param())
553 }
554 
555 impl TemplateParameters for Type {
self_template_params( &self, ctx: &BindgenContext, ) -> Vec<TypeId>556     fn self_template_params(
557         &self,
558         ctx: &BindgenContext,
559     ) -> Vec<TypeId> {
560         self.kind.self_template_params(ctx)
561     }
562 }
563 
564 impl TemplateParameters for TypeKind {
self_template_params( &self, ctx: &BindgenContext, ) -> Vec<TypeId>565     fn self_template_params(
566         &self,
567         ctx: &BindgenContext,
568     ) -> Vec<TypeId> {
569         match *self {
570             TypeKind::ResolvedTypeRef(id) => {
571                 ctx.resolve_type(id).self_template_params(ctx)
572             }
573             TypeKind::Comp(ref comp) => comp.self_template_params(ctx),
574             TypeKind::TemplateAlias(_, ref args) => args.clone(),
575 
576             TypeKind::Opaque |
577             TypeKind::TemplateInstantiation(..) |
578             TypeKind::Void |
579             TypeKind::NullPtr |
580             TypeKind::Int(_) |
581             TypeKind::Float(_) |
582             TypeKind::Complex(_) |
583             TypeKind::Array(..) |
584             TypeKind::Vector(..) |
585             TypeKind::Function(_) |
586             TypeKind::Enum(_) |
587             TypeKind::Pointer(_) |
588             TypeKind::BlockPointer(_) |
589             TypeKind::Reference(_) |
590             TypeKind::UnresolvedTypeRef(..) |
591             TypeKind::TypeParam |
592             TypeKind::Alias(_) |
593             TypeKind::ObjCId |
594             TypeKind::ObjCSel |
595             TypeKind::ObjCInterface(_) => vec![],
596         }
597     }
598 }
599 
600 /// The kind of float this type represents.
601 #[derive(Debug, Copy, Clone, PartialEq)]
602 pub enum FloatKind {
603     /// A `float`.
604     Float,
605     /// A `double`.
606     Double,
607     /// A `long double`.
608     LongDouble,
609     /// A `__float128`.
610     Float128,
611 }
612 
613 /// The different kinds of types that we can parse.
614 #[derive(Debug)]
615 pub enum TypeKind {
616     /// The void type.
617     Void,
618 
619     /// The `nullptr_t` type.
620     NullPtr,
621 
622     /// A compound type, that is, a class, struct, or union.
623     Comp(CompInfo),
624 
625     /// An opaque type that we just don't understand. All usage of this shoulf
626     /// result in an opaque blob of bytes generated from the containing type's
627     /// layout.
628     Opaque,
629 
630     /// An integer type, of a given kind. `bool` and `char` are also considered
631     /// integers.
632     Int(IntKind),
633 
634     /// A floating point type.
635     Float(FloatKind),
636 
637     /// A complex floating point type.
638     Complex(FloatKind),
639 
640     /// A type alias, with a name, that points to another type.
641     Alias(TypeId),
642 
643     /// A templated alias, pointing to an inner type, just as `Alias`, but with
644     /// template parameters.
645     TemplateAlias(TypeId, Vec<TypeId>),
646 
647     /// A packed vector type: element type, number of elements
648     Vector(TypeId, usize),
649 
650     /// An array of a type and a length.
651     Array(TypeId, usize),
652 
653     /// A function type, with a given signature.
654     Function(FunctionSig),
655 
656     /// An `enum` type.
657     Enum(Enum),
658 
659     /// A pointer to a type. The bool field represents whether it's const or
660     /// not.
661     Pointer(TypeId),
662 
663     /// A pointer to an Apple block.
664     BlockPointer(TypeId),
665 
666     /// A reference to a type, as in: int& foo().
667     Reference(TypeId),
668 
669     /// An instantiation of an abstract template definition with a set of
670     /// concrete template arguments.
671     TemplateInstantiation(TemplateInstantiation),
672 
673     /// A reference to a yet-to-resolve type. This stores the clang cursor
674     /// itself, and postpones its resolution.
675     ///
676     /// These are gone in a phase after parsing where these are mapped to
677     /// already known types, and are converted to ResolvedTypeRef.
678     ///
679     /// see tests/headers/typeref.hpp to see somewhere where this is a problem.
680     UnresolvedTypeRef(
681         clang::Type,
682         clang::Cursor,
683         /* parent_id */
684         Option<ItemId>
685     ),
686 
687     /// An indirection to another type.
688     ///
689     /// These are generated after we resolve a forward declaration, or when we
690     /// replace one type with another.
691     ResolvedTypeRef(TypeId),
692 
693     /// A named type, that is, a template parameter.
694     TypeParam,
695 
696     /// Objective C interface. Always referenced through a pointer
697     ObjCInterface(ObjCInterface),
698 
699     /// Objective C 'id' type, points to any object
700     ObjCId,
701 
702     /// Objective C selector type
703     ObjCSel,
704 }
705 
706 impl Type {
707     /// This is another of the nasty methods. This one is the one that takes
708     /// care of the core logic of converting a clang type to a `Type`.
709     ///
710     /// It's sort of nasty and full of special-casing, but hopefully the
711     /// comments in every special case justify why they're there.
from_clang_ty( potential_id: ItemId, ty: &clang::Type, location: Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<ParseResult<Self>, ParseError>712     pub fn from_clang_ty(
713         potential_id: ItemId,
714         ty: &clang::Type,
715         location: Cursor,
716         parent_id: Option<ItemId>,
717         ctx: &mut BindgenContext,
718     ) -> Result<ParseResult<Self>, ParseError> {
719         use clang_sys::*;
720         {
721             let already_resolved = ctx.builtin_or_resolved_ty(
722                 potential_id,
723                 parent_id,
724                 ty,
725                 Some(location),
726             );
727             if let Some(ty) = already_resolved {
728                 debug!("{:?} already resolved: {:?}", ty, location);
729                 return Ok(ParseResult::AlreadyResolved(ty.into()));
730             }
731         }
732 
733         let layout = ty.fallible_layout(ctx).ok();
734         let cursor = ty.declaration();
735         let mut name = cursor.spelling();
736 
737         debug!(
738             "from_clang_ty: {:?}, ty: {:?}, loc: {:?}",
739             potential_id,
740             ty,
741             location
742         );
743         debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types());
744 
745         let canonical_ty = ty.canonical_type();
746 
747         // Parse objc protocols as if they were interfaces
748         let mut ty_kind = ty.kind();
749         match location.kind() {
750             CXCursor_ObjCProtocolDecl |
751             CXCursor_ObjCCategoryDecl => ty_kind = CXType_ObjCInterface,
752             _ => {}
753         }
754 
755         // Objective C template type parameter
756         // FIXME: This is probably wrong, we are attempting to find the
757         //        objc template params, which seem to manifest as a typedef.
758         //        We are rewriting them as id to suppress multiple conflicting
759         //        typedefs at root level
760         if ty_kind == CXType_Typedef {
761             let is_template_type_param = ty.declaration().kind() ==
762                 CXCursor_TemplateTypeParameter;
763             let is_canonical_objcpointer = canonical_ty.kind() ==
764                 CXType_ObjCObjectPointer;
765 
766             // We have found a template type for objc interface
767             if is_canonical_objcpointer && is_template_type_param {
768                 // Objective-C generics are just ids with fancy name.
769                 // To keep it simple, just name them ids
770                 name = "id".to_owned();
771             }
772 
773         }
774 
775         if location.kind() == CXCursor_ClassTemplatePartialSpecialization {
776             // Sorry! (Not sorry)
777             warn!(
778                 "Found a partial template specialization; bindgen does not \
779                    support partial template specialization! Constructing \
780                    opaque type instead."
781             );
782             return Ok(
783                 ParseResult::New(Opaque::from_clang_ty(&canonical_ty, ctx), None),
784             );
785         }
786 
787         let kind = if location.kind() == CXCursor_TemplateRef ||
788             (ty.template_args().is_some() && ty_kind != CXType_Typedef)
789         {
790             // This is a template instantiation.
791             match TemplateInstantiation::from_ty(&ty, ctx) {
792                 Some(inst) => TypeKind::TemplateInstantiation(inst),
793                 None => TypeKind::Opaque,
794             }
795         } else {
796             match ty_kind {
797                 CXType_Unexposed if *ty != canonical_ty &&
798                                     canonical_ty.kind() != CXType_Invalid &&
799                                     ty.ret_type().is_none() &&
800                                     // Sometime clang desugars some types more than
801                                     // what we need, specially with function
802                                     // pointers.
803                                     //
804                                     // We should also try the solution of inverting
805                                     // those checks instead of doing this, that is,
806                                     // something like:
807                                     //
808                                     // CXType_Unexposed if ty.ret_type().is_some()
809                                     //   => { ... }
810                                     //
811                                     // etc.
812                                     !canonical_ty.spelling().contains("type-parameter") => {
813                     debug!("Looking for canonical type: {:?}", canonical_ty);
814                     return Self::from_clang_ty(potential_id,
815                                                &canonical_ty,
816                                                location,
817                                                parent_id,
818                                                ctx);
819                 }
820                 CXType_Unexposed | CXType_Invalid => {
821                     // For some reason Clang doesn't give us any hint in some
822                     // situations where we should generate a function pointer (see
823                     // tests/headers/func_ptr_in_struct.h), so we do a guess here
824                     // trying to see if it has a valid return type.
825                     if ty.ret_type().is_some() {
826                         let signature =
827                             FunctionSig::from_ty(ty, &location, ctx)?;
828                         TypeKind::Function(signature)
829                     // Same here, with template specialisations we can safely
830                     // assume this is a Comp(..)
831                     } else if ty.is_fully_instantiated_template() {
832                         debug!(
833                             "Template specialization: {:?}, {:?} {:?}",
834                             ty,
835                             location,
836                             canonical_ty
837                         );
838                         let complex = CompInfo::from_ty(
839                             potential_id,
840                             ty,
841                             Some(location),
842                             ctx,
843                         ).expect("C'mon");
844                         TypeKind::Comp(complex)
845                     } else {
846                         match location.kind() {
847                             CXCursor_CXXBaseSpecifier |
848                             CXCursor_ClassTemplate => {
849                                 if location.kind() ==
850                                     CXCursor_CXXBaseSpecifier
851                                 {
852                                     // In the case we're parsing a base specifier
853                                     // inside an unexposed or invalid type, it means
854                                     // that we're parsing one of two things:
855                                     //
856                                     //  * A template parameter.
857                                     //  * A complex class that isn't exposed.
858                                     //
859                                     // This means, unfortunately, that there's no
860                                     // good way to differentiate between them.
861                                     //
862                                     // Probably we could try to look at the
863                                     // declaration and complicate more this logic,
864                                     // but we'll keep it simple... if it's a valid
865                                     // C++ identifier, we'll consider it as a
866                                     // template parameter.
867                                     //
868                                     // This is because:
869                                     //
870                                     //  * We expect every other base that is a
871                                     //    proper identifier (that is, a simple
872                                     //    struct/union declaration), to be exposed,
873                                     //    so this path can't be reached in that
874                                     //    case.
875                                     //
876                                     //  * Quite conveniently, complex base
877                                     //    specifiers preserve their full names (that
878                                     //    is: Foo<T> instead of Foo). We can take
879                                     //    advantage of this.
880                                     //
881                                     // If we find some edge case where this doesn't
882                                     // work (which I guess is unlikely, see the
883                                     // different test cases[1][2][3][4]), we'd need
884                                     // to find more creative ways of differentiating
885                                     // these two cases.
886                                     //
887                                     // [1]: inherit_named.hpp
888                                     // [2]: forward-inherit-struct-with-fields.hpp
889                                     // [3]: forward-inherit-struct.hpp
890                                     // [4]: inherit-namespaced.hpp
891                                     if location.spelling().chars().all(|c| {
892                                         c.is_alphanumeric() || c == '_'
893                                     })
894                                     {
895                                         return Err(ParseError::Recurse);
896                                     }
897                                 } else {
898                                     name = location.spelling();
899                                 }
900 
901                                 let complex = CompInfo::from_ty(
902                                     potential_id,
903                                     ty,
904                                     Some(location),
905                                     ctx,
906                                 );
907                                 match complex {
908                                     Ok(complex) => TypeKind::Comp(complex),
909                                     Err(_) => {
910                                         warn!(
911                                             "Could not create complex type \
912                                                from class template or base \
913                                                specifier, using opaque blob"
914                                         );
915                                         let opaque = Opaque::from_clang_ty(ty, ctx);
916                                         return Ok(
917                                             ParseResult::New(opaque, None),
918                                         );
919                                     }
920                                 }
921                             }
922                             CXCursor_TypeAliasTemplateDecl => {
923                                 debug!("TypeAliasTemplateDecl");
924 
925                                 // We need to manually unwind this one.
926                                 let mut inner = Err(ParseError::Continue);
927                                 let mut args = vec![];
928 
929                                 location.visit(|cur| {
930                                     match cur.kind() {
931                                         CXCursor_TypeAliasDecl => {
932                                             let current = cur.cur_type();
933 
934                                             debug_assert_eq!(
935                                                 current.kind(),
936                                                 CXType_Typedef
937                                             );
938 
939                                             name = current.spelling();
940 
941                                             let inner_ty = cur.typedef_type()
942                                                 .expect("Not valid Type?");
943                                             inner = Ok(Item::from_ty_or_ref(
944                                                 inner_ty,
945                                                 cur,
946                                                 Some(potential_id),
947                                                 ctx,
948                                             ));
949                                         }
950                                         CXCursor_TemplateTypeParameter => {
951                                             let param =
952                                                 Item::type_param(None,
953                                                                  cur,
954                                                                  ctx)
955                                                 .expect("Item::type_param shouldn't \
956                                                          ever fail if we are looking \
957                                                          at a TemplateTypeParameter");
958                                             args.push(param);
959                                         }
960                                         _ => {}
961                                     }
962                                     CXChildVisit_Continue
963                                 });
964 
965                                 let inner_type = match inner {
966                                     Ok(inner) => inner,
967                                     Err(..) => {
968                                         error!(
969                                             "Failed to parse template alias \
970                                                {:?}",
971                                             location
972                                         );
973                                         return Err(ParseError::Continue);
974                                     }
975                                 };
976 
977                                 TypeKind::TemplateAlias(inner_type, args)
978                             }
979                             CXCursor_TemplateRef => {
980                                 let referenced = location.referenced().unwrap();
981                                 let referenced_ty = referenced.cur_type();
982 
983                                 debug!(
984                                     "TemplateRef: location = {:?}; referenced = \
985                                         {:?}; referenced_ty = {:?}",
986                                     location,
987                                     referenced,
988                                     referenced_ty
989                                 );
990 
991                                 return Self::from_clang_ty(
992                                     potential_id,
993                                     &referenced_ty,
994                                     referenced,
995                                     parent_id,
996                                     ctx,
997                                 );
998                             }
999                             CXCursor_TypeRef => {
1000                                 let referenced = location.referenced().unwrap();
1001                                 let referenced_ty = referenced.cur_type();
1002                                 let declaration = referenced_ty.declaration();
1003 
1004                                 debug!(
1005                                     "TypeRef: location = {:?}; referenced = \
1006                                         {:?}; referenced_ty = {:?}",
1007                                     location,
1008                                     referenced,
1009                                     referenced_ty
1010                                 );
1011 
1012                                 let id = Item::from_ty_or_ref_with_id(
1013                                     potential_id,
1014                                     referenced_ty,
1015                                     declaration,
1016                                     parent_id,
1017                                     ctx,
1018                                 );
1019                                 return Ok(ParseResult::AlreadyResolved(id.into()));
1020                             }
1021                             CXCursor_NamespaceRef => {
1022                                 return Err(ParseError::Continue);
1023                             }
1024                             _ => {
1025                                 if ty.kind() == CXType_Unexposed {
1026                                     warn!(
1027                                         "Unexposed type {:?}, recursing inside, \
1028                                           loc: {:?}",
1029                                         ty,
1030                                         location
1031                                     );
1032                                     return Err(ParseError::Recurse);
1033                                 }
1034 
1035                                 warn!("invalid type {:?}", ty);
1036                                 return Err(ParseError::Continue);
1037                             }
1038                         }
1039                     }
1040                 }
1041                 CXType_Auto => {
1042                     if canonical_ty == *ty {
1043                         debug!("Couldn't find deduced type: {:?}", ty);
1044                         return Err(ParseError::Continue);
1045                     }
1046 
1047                     return Self::from_clang_ty(
1048                         potential_id,
1049                         &canonical_ty,
1050                         location,
1051                         parent_id,
1052                         ctx,
1053                     );
1054                 }
1055                 // NOTE: We don't resolve pointers eagerly because the pointee type
1056                 // might not have been parsed, and if it contains templates or
1057                 // something else we might get confused, see the comment inside
1058                 // TypeRef.
1059                 //
1060                 // We might need to, though, if the context is already in the
1061                 // process of resolving them.
1062                 CXType_ObjCObjectPointer |
1063                 CXType_MemberPointer |
1064                 CXType_Pointer => {
1065                     let pointee = ty.pointee_type().unwrap();
1066                     let inner =
1067                         Item::from_ty_or_ref(pointee, location, None, ctx);
1068                     TypeKind::Pointer(inner)
1069                 }
1070                 CXType_BlockPointer => {
1071                     let pointee = ty.pointee_type().expect("Not valid Type?");
1072                     let inner =
1073                         Item::from_ty_or_ref(pointee, location, None, ctx);
1074                     TypeKind::BlockPointer(inner)
1075                 },
1076                 // XXX: RValueReference is most likely wrong, but I don't think we
1077                 // can even add bindings for that, so huh.
1078                 CXType_RValueReference |
1079                 CXType_LValueReference => {
1080                     let inner = Item::from_ty_or_ref(
1081                         ty.pointee_type().unwrap(),
1082                         location,
1083                         None,
1084                         ctx,
1085                     );
1086                     TypeKind::Reference(inner)
1087                 }
1088                 // XXX DependentSizedArray is wrong
1089                 CXType_VariableArray |
1090                 CXType_DependentSizedArray => {
1091                     let inner = Item::from_ty(
1092                         ty.elem_type().as_ref().unwrap(),
1093                         location,
1094                         None,
1095                         ctx,
1096                     ).expect("Not able to resolve array element?");
1097                     TypeKind::Pointer(inner)
1098                 }
1099                 CXType_IncompleteArray => {
1100                     let inner = Item::from_ty(
1101                         ty.elem_type().as_ref().unwrap(),
1102                         location,
1103                         None,
1104                         ctx,
1105                     ).expect("Not able to resolve array element?");
1106                     TypeKind::Array(inner, 0)
1107                 }
1108                 CXType_FunctionNoProto |
1109                 CXType_FunctionProto => {
1110                     let signature =
1111                         FunctionSig::from_ty(ty, &location, ctx)?;
1112                     TypeKind::Function(signature)
1113                 }
1114                 CXType_Typedef => {
1115                     let inner = cursor.typedef_type().expect("Not valid Type?");
1116                     let inner =
1117                         Item::from_ty_or_ref(inner, location, None, ctx);
1118                     TypeKind::Alias(inner)
1119                 }
1120                 CXType_Enum => {
1121                     let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?");
1122 
1123                     if name.is_empty() {
1124                         let pretty_name = ty.spelling();
1125                         if clang::is_valid_identifier(&pretty_name) {
1126                             name = pretty_name;
1127                         }
1128                     }
1129 
1130                     TypeKind::Enum(enum_)
1131                 }
1132                 CXType_Record => {
1133                     let complex = CompInfo::from_ty(
1134                         potential_id,
1135                         ty,
1136                         Some(location),
1137                         ctx,
1138                     ).expect("Not a complex type?");
1139 
1140                     if name.is_empty() {
1141                         // The pretty-printed name may contain typedefed name,
1142                         // but may also be "struct (anonymous at .h:1)"
1143                         let pretty_name = ty.spelling();
1144                         if clang::is_valid_identifier(&pretty_name) {
1145                             name = pretty_name;
1146                         }
1147                     }
1148 
1149                     TypeKind::Comp(complex)
1150                 }
1151                 CXType_Vector => {
1152                     let inner = Item::from_ty(
1153                         ty.elem_type().as_ref().unwrap(),
1154                         location,
1155                         None,
1156                         ctx,
1157                     ).expect("Not able to resolve vector element?");
1158                     TypeKind::Vector(inner, ty.num_elements().unwrap())
1159                 }
1160                 CXType_ConstantArray => {
1161                     let inner = Item::from_ty(
1162                         ty.elem_type().as_ref().unwrap(),
1163                         location,
1164                         None,
1165                         ctx,
1166                     ).expect("Not able to resolve array element?");
1167                     TypeKind::Array(inner, ty.num_elements().unwrap())
1168                 }
1169                 CXType_Elaborated => {
1170                     return Self::from_clang_ty(
1171                         potential_id,
1172                         &ty.named(),
1173                         location,
1174                         parent_id,
1175                         ctx,
1176                     );
1177                 }
1178                 CXType_ObjCId => TypeKind::ObjCId,
1179                 CXType_ObjCSel => TypeKind::ObjCSel,
1180                 CXType_ObjCClass |
1181                 CXType_ObjCInterface => {
1182                     let interface = ObjCInterface::from_ty(&location, ctx)
1183                         .expect("Not a valid objc interface?");
1184                     name = interface.rust_name();
1185                     TypeKind::ObjCInterface(interface)
1186                 }
1187                 CXType_Dependent => {
1188                     return Err(ParseError::Continue);
1189                 }
1190                 _ => {
1191                     error!(
1192                         "unsupported type: kind = {:?}; ty = {:?}; at {:?}",
1193                         ty.kind(),
1194                         ty,
1195                         location
1196                     );
1197                     return Err(ParseError::Continue);
1198                 }
1199             }
1200         };
1201 
1202         let name = if name.is_empty() { None } else { Some(name) };
1203 
1204         let is_const = ty.is_const();
1205 
1206         let ty = Type::new(name, layout, kind, is_const);
1207         // TODO: maybe declaration.canonical()?
1208         Ok(ParseResult::New(ty, Some(cursor.canonical())))
1209     }
1210 }
1211 
1212 impl Trace for Type {
1213     type Extra = Item;
1214 
trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item) where T: Tracer,1215     fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
1216     where
1217         T: Tracer,
1218     {
1219         match *self.kind() {
1220             TypeKind::Pointer(inner) |
1221             TypeKind::Reference(inner) |
1222             TypeKind::Array(inner, _) |
1223             TypeKind::Vector(inner, _) |
1224             TypeKind::BlockPointer(inner) |
1225             TypeKind::Alias(inner) |
1226             TypeKind::ResolvedTypeRef(inner) => {
1227                 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1228             }
1229             TypeKind::TemplateAlias(inner, ref template_params) => {
1230                 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1231                 for param in template_params {
1232                     tracer.visit_kind(
1233                         param.into(),
1234                         EdgeKind::TemplateParameterDefinition,
1235                     );
1236                 }
1237             }
1238             TypeKind::TemplateInstantiation(ref inst) => {
1239                 inst.trace(context, tracer, &());
1240             }
1241             TypeKind::Comp(ref ci) => ci.trace(context, tracer, item),
1242             TypeKind::Function(ref sig) => sig.trace(context, tracer, &()),
1243             TypeKind::Enum(ref en) => {
1244                 if let Some(repr) = en.repr() {
1245                     tracer.visit(repr.into());
1246                 }
1247             }
1248             TypeKind::UnresolvedTypeRef(_, _, Some(id)) => {
1249                 tracer.visit(id);
1250             }
1251 
1252             TypeKind::ObjCInterface(ref interface) => {
1253                 interface.trace(context, tracer, &());
1254             }
1255 
1256             // None of these variants have edges to other items and types.
1257             TypeKind::Opaque |
1258             TypeKind::UnresolvedTypeRef(_, _, None) |
1259             TypeKind::TypeParam |
1260             TypeKind::Void |
1261             TypeKind::NullPtr |
1262             TypeKind::Int(_) |
1263             TypeKind::Float(_) |
1264             TypeKind::Complex(_) |
1265             TypeKind::ObjCId |
1266             TypeKind::ObjCSel => {}
1267         }
1268     }
1269 }
1270