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