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