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