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