• 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::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 `float`.
562     Float,
563     /// A `double`.
564     Double,
565     /// A `long double`.
566     LongDouble,
567     /// A `__float128`.
568     Float128,
569 }
570 
571 /// The different kinds of types that we can parse.
572 #[derive(Debug)]
573 pub(crate) enum TypeKind {
574     /// The void type.
575     Void,
576 
577     /// The `nullptr_t` type.
578     NullPtr,
579 
580     /// A compound type, that is, a class, struct, or union.
581     Comp(CompInfo),
582 
583     /// An opaque type that we just don't understand. All usage of this shoulf
584     /// result in an opaque blob of bytes generated from the containing type's
585     /// layout.
586     Opaque,
587 
588     /// An integer type, of a given kind. `bool` and `char` are also considered
589     /// integers.
590     Int(IntKind),
591 
592     /// A floating point type.
593     Float(FloatKind),
594 
595     /// A complex floating point type.
596     Complex(FloatKind),
597 
598     /// A type alias, with a name, that points to another type.
599     Alias(TypeId),
600 
601     /// A templated alias, pointing to an inner type, just as `Alias`, but with
602     /// template parameters.
603     TemplateAlias(TypeId, Vec<TypeId>),
604 
605     /// A packed vector type: element type, number of elements
606     Vector(TypeId, usize),
607 
608     /// An array of a type and a length.
609     Array(TypeId, usize),
610 
611     /// A function type, with a given signature.
612     Function(FunctionSig),
613 
614     /// An `enum` type.
615     Enum(Enum),
616 
617     /// A pointer to a type. The bool field represents whether it's const or
618     /// not.
619     Pointer(TypeId),
620 
621     /// A pointer to an Apple block.
622     BlockPointer(TypeId),
623 
624     /// A reference to a type, as in: int& foo().
625     Reference(TypeId),
626 
627     /// An instantiation of an abstract template definition with a set of
628     /// concrete template arguments.
629     TemplateInstantiation(TemplateInstantiation),
630 
631     /// A reference to a yet-to-resolve type. This stores the clang cursor
632     /// itself, and postpones its resolution.
633     ///
634     /// These are gone in a phase after parsing where these are mapped to
635     /// already known types, and are converted to ResolvedTypeRef.
636     ///
637     /// see tests/headers/typeref.hpp to see somewhere where this is a problem.
638     UnresolvedTypeRef(
639         clang::Type,
640         clang::Cursor,
641         /* parent_id */
642         Option<ItemId>,
643     ),
644 
645     /// An indirection to another type.
646     ///
647     /// These are generated after we resolve a forward declaration, or when we
648     /// replace one type with another.
649     ResolvedTypeRef(TypeId),
650 
651     /// A named type, that is, a template parameter.
652     TypeParam,
653 
654     /// Objective C interface. Always referenced through a pointer
655     ObjCInterface(ObjCInterface),
656 
657     /// Objective C 'id' type, points to any object
658     ObjCId,
659 
660     /// Objective C selector type
661     ObjCSel,
662 }
663 
664 impl Type {
665     /// This is another of the nasty methods. This one is the one that takes
666     /// care of the core logic of converting a clang type to a `Type`.
667     ///
668     /// It's sort of nasty and full of special-casing, but hopefully the
669     /// 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>670     pub(crate) fn from_clang_ty(
671         potential_id: ItemId,
672         ty: &clang::Type,
673         location: Cursor,
674         parent_id: Option<ItemId>,
675         ctx: &mut BindgenContext,
676     ) -> Result<ParseResult<Self>, ParseError> {
677         use clang_sys::*;
678         {
679             let already_resolved = ctx.builtin_or_resolved_ty(
680                 potential_id,
681                 parent_id,
682                 ty,
683                 Some(location),
684             );
685             if let Some(ty) = already_resolved {
686                 debug!("{:?} already resolved: {:?}", ty, location);
687                 return Ok(ParseResult::AlreadyResolved(ty.into()));
688             }
689         }
690 
691         let layout = ty.fallible_layout(ctx).ok();
692         let cursor = ty.declaration();
693         let is_anonymous = cursor.is_anonymous();
694         let mut name = if is_anonymous {
695             None
696         } else {
697             Some(cursor.spelling()).filter(|n| !n.is_empty())
698         };
699 
700         debug!(
701             "from_clang_ty: {:?}, ty: {:?}, loc: {:?}",
702             potential_id, ty, location
703         );
704         debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types());
705 
706         let canonical_ty = ty.canonical_type();
707 
708         // Parse objc protocols as if they were interfaces
709         let mut ty_kind = ty.kind();
710         match location.kind() {
711             CXCursor_ObjCProtocolDecl | CXCursor_ObjCCategoryDecl => {
712                 ty_kind = CXType_ObjCInterface
713             }
714             _ => {}
715         }
716 
717         // Objective C template type parameter
718         // FIXME: This is probably wrong, we are attempting to find the
719         //        objc template params, which seem to manifest as a typedef.
720         //        We are rewriting them as ID to suppress multiple conflicting
721         //        typedefs at root level
722         if ty_kind == CXType_Typedef {
723             let is_template_type_param =
724                 ty.declaration().kind() == CXCursor_TemplateTypeParameter;
725             let is_canonical_objcpointer =
726                 canonical_ty.kind() == CXType_ObjCObjectPointer;
727 
728             // We have found a template type for objc interface
729             if is_canonical_objcpointer && is_template_type_param {
730                 // Objective-C generics are just ids with fancy name.
731                 // To keep it simple, just name them ids
732                 name = Some("id".to_owned());
733             }
734         }
735 
736         if location.kind() == CXCursor_ClassTemplatePartialSpecialization {
737             // Sorry! (Not sorry)
738             warn!(
739                 "Found a partial template specialization; bindgen does not \
740                  support partial template specialization! Constructing \
741                  opaque type instead."
742             );
743             return Ok(ParseResult::New(
744                 Opaque::from_clang_ty(&canonical_ty, ctx),
745                 None,
746             ));
747         }
748 
749         let kind = if location.kind() == CXCursor_TemplateRef ||
750             (ty.template_args().is_some() && ty_kind != CXType_Typedef)
751         {
752             // This is a template instantiation.
753             match TemplateInstantiation::from_ty(ty, ctx) {
754                 Some(inst) => TypeKind::TemplateInstantiation(inst),
755                 None => TypeKind::Opaque,
756             }
757         } else {
758             match ty_kind {
759                 CXType_Unexposed
760                     if *ty != canonical_ty &&
761                                     canonical_ty.kind() != CXType_Invalid &&
762                                     ty.ret_type().is_none() &&
763                                     // Sometime clang desugars some types more than
764                                     // what we need, specially with function
765                                     // pointers.
766                                     //
767                                     // We should also try the solution of inverting
768                                     // those checks instead of doing this, that is,
769                                     // something like:
770                                     //
771                                     // CXType_Unexposed if ty.ret_type().is_some()
772                                     //   => { ... }
773                                     //
774                                     // etc.
775                                     !canonical_ty.spelling().contains("type-parameter") =>
776                 {
777                     debug!("Looking for canonical type: {:?}", canonical_ty);
778                     return Self::from_clang_ty(
779                         potential_id,
780                         &canonical_ty,
781                         location,
782                         parent_id,
783                         ctx,
784                     );
785                 }
786                 CXType_Unexposed | CXType_Invalid => {
787                     // For some reason Clang doesn't give us any hint in some
788                     // situations where we should generate a function pointer (see
789                     // tests/headers/func_ptr_in_struct.h), so we do a guess here
790                     // trying to see if it has a valid return type.
791                     if ty.ret_type().is_some() {
792                         let signature =
793                             FunctionSig::from_ty(ty, &location, ctx)?;
794                         TypeKind::Function(signature)
795                     // Same here, with template specialisations we can safely
796                     // assume this is a Comp(..)
797                     } else if ty.is_fully_instantiated_template() {
798                         debug!(
799                             "Template specialization: {:?}, {:?} {:?}",
800                             ty, location, canonical_ty
801                         );
802                         let complex = CompInfo::from_ty(
803                             potential_id,
804                             ty,
805                             Some(location),
806                             ctx,
807                         )
808                         .expect("C'mon");
809                         TypeKind::Comp(complex)
810                     } else {
811                         match location.kind() {
812                             CXCursor_CXXBaseSpecifier |
813                             CXCursor_ClassTemplate => {
814                                 if location.kind() == CXCursor_CXXBaseSpecifier
815                                 {
816                                     // In the case we're parsing a base specifier
817                                     // inside an unexposed or invalid type, it means
818                                     // that we're parsing one of two things:
819                                     //
820                                     //  * A template parameter.
821                                     //  * A complex class that isn't exposed.
822                                     //
823                                     // This means, unfortunately, that there's no
824                                     // good way to differentiate between them.
825                                     //
826                                     // Probably we could try to look at the
827                                     // declaration and complicate more this logic,
828                                     // but we'll keep it simple... if it's a valid
829                                     // C++ identifier, we'll consider it as a
830                                     // template parameter.
831                                     //
832                                     // This is because:
833                                     //
834                                     //  * We expect every other base that is a
835                                     //    proper identifier (that is, a simple
836                                     //    struct/union declaration), to be exposed,
837                                     //    so this path can't be reached in that
838                                     //    case.
839                                     //
840                                     //  * Quite conveniently, complex base
841                                     //    specifiers preserve their full names (that
842                                     //    is: Foo<T> instead of Foo). We can take
843                                     //    advantage of this.
844                                     //
845                                     // If we find some edge case where this doesn't
846                                     // work (which I guess is unlikely, see the
847                                     // different test cases[1][2][3][4]), we'd need
848                                     // to find more creative ways of differentiating
849                                     // these two cases.
850                                     //
851                                     // [1]: inherit_named.hpp
852                                     // [2]: forward-inherit-struct-with-fields.hpp
853                                     // [3]: forward-inherit-struct.hpp
854                                     // [4]: inherit-namespaced.hpp
855                                     if location.spelling().chars().all(|c| {
856                                         c.is_alphanumeric() || c == '_'
857                                     }) {
858                                         return Err(ParseError::Recurse);
859                                     }
860                                 } else {
861                                     name = Some(location.spelling());
862                                 }
863 
864                                 let complex = CompInfo::from_ty(
865                                     potential_id,
866                                     ty,
867                                     Some(location),
868                                     ctx,
869                                 );
870                                 match complex {
871                                     Ok(complex) => TypeKind::Comp(complex),
872                                     Err(_) => {
873                                         warn!(
874                                             "Could not create complex type \
875                                              from class template or base \
876                                              specifier, using opaque blob"
877                                         );
878                                         let opaque =
879                                             Opaque::from_clang_ty(ty, ctx);
880                                         return Ok(ParseResult::New(
881                                             opaque, None,
882                                         ));
883                                     }
884                                 }
885                             }
886                             CXCursor_TypeAliasTemplateDecl => {
887                                 debug!("TypeAliasTemplateDecl");
888 
889                                 // We need to manually unwind this one.
890                                 let mut inner = Err(ParseError::Continue);
891                                 let mut args = vec![];
892 
893                                 location.visit(|cur| {
894                                     match cur.kind() {
895                                         CXCursor_TypeAliasDecl => {
896                                             let current = cur.cur_type();
897 
898                                             debug_assert_eq!(
899                                                 current.kind(),
900                                                 CXType_Typedef
901                                             );
902 
903                                             name = Some(location.spelling());
904 
905                                             let inner_ty = cur
906                                                 .typedef_type()
907                                                 .expect("Not valid Type?");
908                                             inner = Ok(Item::from_ty_or_ref(
909                                                 inner_ty,
910                                                 cur,
911                                                 Some(potential_id),
912                                                 ctx,
913                                             ));
914                                         }
915                                         CXCursor_TemplateTypeParameter => {
916                                             let param = Item::type_param(
917                                                 None, cur, ctx,
918                                             )
919                                             .expect(
920                                                 "Item::type_param shouldn't \
921                                                  ever fail if we are looking \
922                                                  at a TemplateTypeParameter",
923                                             );
924                                             args.push(param);
925                                         }
926                                         _ => {}
927                                     }
928                                     CXChildVisit_Continue
929                                 });
930 
931                                 let inner_type = match inner {
932                                     Ok(inner) => inner,
933                                     Err(..) => {
934                                         warn!(
935                                             "Failed to parse template alias \
936                                              {:?}",
937                                             location
938                                         );
939                                         return Err(ParseError::Continue);
940                                     }
941                                 };
942 
943                                 TypeKind::TemplateAlias(inner_type, args)
944                             }
945                             CXCursor_TemplateRef => {
946                                 let referenced = location.referenced().unwrap();
947                                 let referenced_ty = referenced.cur_type();
948 
949                                 debug!(
950                                     "TemplateRef: location = {:?}; referenced = \
951                                         {:?}; referenced_ty = {:?}",
952                                     location,
953                                     referenced,
954                                     referenced_ty
955                                 );
956 
957                                 return Self::from_clang_ty(
958                                     potential_id,
959                                     &referenced_ty,
960                                     referenced,
961                                     parent_id,
962                                     ctx,
963                                 );
964                             }
965                             CXCursor_TypeRef => {
966                                 let referenced = location.referenced().unwrap();
967                                 let referenced_ty = referenced.cur_type();
968                                 let declaration = referenced_ty.declaration();
969 
970                                 debug!(
971                                     "TypeRef: location = {:?}; referenced = \
972                                      {:?}; referenced_ty = {:?}",
973                                     location, referenced, referenced_ty
974                                 );
975 
976                                 let id = Item::from_ty_or_ref_with_id(
977                                     potential_id,
978                                     referenced_ty,
979                                     declaration,
980                                     parent_id,
981                                     ctx,
982                                 );
983                                 return Ok(ParseResult::AlreadyResolved(
984                                     id.into(),
985                                 ));
986                             }
987                             CXCursor_NamespaceRef => {
988                                 return Err(ParseError::Continue);
989                             }
990                             _ => {
991                                 if ty.kind() == CXType_Unexposed {
992                                     warn!(
993                                         "Unexposed type {:?}, recursing inside, \
994                                           loc: {:?}",
995                                         ty,
996                                         location
997                                     );
998                                     return Err(ParseError::Recurse);
999                                 }
1000 
1001                                 warn!("invalid type {:?}", ty);
1002                                 return Err(ParseError::Continue);
1003                             }
1004                         }
1005                     }
1006                 }
1007                 CXType_Auto => {
1008                     if canonical_ty == *ty {
1009                         debug!("Couldn't find deduced type: {:?}", ty);
1010                         return Err(ParseError::Continue);
1011                     }
1012 
1013                     return Self::from_clang_ty(
1014                         potential_id,
1015                         &canonical_ty,
1016                         location,
1017                         parent_id,
1018                         ctx,
1019                     );
1020                 }
1021                 // NOTE: We don't resolve pointers eagerly because the pointee type
1022                 // might not have been parsed, and if it contains templates or
1023                 // something else we might get confused, see the comment inside
1024                 // TypeRef.
1025                 //
1026                 // We might need to, though, if the context is already in the
1027                 // process of resolving them.
1028                 CXType_ObjCObjectPointer |
1029                 CXType_MemberPointer |
1030                 CXType_Pointer => {
1031                     let mut pointee = ty.pointee_type().unwrap();
1032                     if *ty != canonical_ty {
1033                         let canonical_pointee =
1034                             canonical_ty.pointee_type().unwrap();
1035                         // clang sometimes loses pointee constness here, see
1036                         // #2244.
1037                         if canonical_pointee.is_const() != pointee.is_const() {
1038                             pointee = canonical_pointee;
1039                         }
1040                     }
1041                     let inner =
1042                         Item::from_ty_or_ref(pointee, location, None, ctx);
1043                     TypeKind::Pointer(inner)
1044                 }
1045                 CXType_BlockPointer => {
1046                     let pointee = ty.pointee_type().expect("Not valid Type?");
1047                     let inner =
1048                         Item::from_ty_or_ref(pointee, location, None, ctx);
1049                     TypeKind::BlockPointer(inner)
1050                 }
1051                 // XXX: RValueReference is most likely wrong, but I don't think we
1052                 // can even add bindings for that, so huh.
1053                 CXType_RValueReference | CXType_LValueReference => {
1054                     let inner = Item::from_ty_or_ref(
1055                         ty.pointee_type().unwrap(),
1056                         location,
1057                         None,
1058                         ctx,
1059                     );
1060                     TypeKind::Reference(inner)
1061                 }
1062                 // XXX DependentSizedArray is wrong
1063                 CXType_VariableArray | CXType_DependentSizedArray => {
1064                     let inner = Item::from_ty(
1065                         ty.elem_type().as_ref().unwrap(),
1066                         location,
1067                         None,
1068                         ctx,
1069                     )
1070                     .expect("Not able to resolve array element?");
1071                     TypeKind::Pointer(inner)
1072                 }
1073                 CXType_IncompleteArray => {
1074                     let inner = Item::from_ty(
1075                         ty.elem_type().as_ref().unwrap(),
1076                         location,
1077                         None,
1078                         ctx,
1079                     )
1080                     .expect("Not able to resolve array element?");
1081                     TypeKind::Array(inner, 0)
1082                 }
1083                 CXType_FunctionNoProto | CXType_FunctionProto => {
1084                     let signature = FunctionSig::from_ty(ty, &location, ctx)?;
1085                     TypeKind::Function(signature)
1086                 }
1087                 CXType_Typedef => {
1088                     let inner = cursor.typedef_type().expect("Not valid Type?");
1089                     let inner_id =
1090                         Item::from_ty_or_ref(inner, location, None, ctx);
1091                     if inner_id == potential_id {
1092                         warn!(
1093                             "Generating oqaque type instead of self-referential \
1094                             typedef");
1095                         // This can happen if we bail out of recursive situations
1096                         // within the clang parsing.
1097                         TypeKind::Opaque
1098                     } else {
1099                         // Check if this type definition is an alias to a pointer of a `struct` /
1100                         // `union` / `enum` with the same name and add the `_ptr` suffix to it to
1101                         // avoid name collisions.
1102                         if let Some(ref mut name) = name {
1103                             if inner.kind() == CXType_Pointer &&
1104                                 !ctx.options().c_naming
1105                             {
1106                                 let pointee = inner.pointee_type().unwrap();
1107                                 if pointee.kind() == CXType_Elaborated &&
1108                                     pointee.declaration().spelling() == *name
1109                                 {
1110                                     *name += "_ptr";
1111                                 }
1112                             }
1113                         }
1114                         TypeKind::Alias(inner_id)
1115                     }
1116                 }
1117                 CXType_Enum => {
1118                     let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?");
1119 
1120                     if !is_anonymous {
1121                         let pretty_name = ty.spelling();
1122                         if clang::is_valid_identifier(&pretty_name) {
1123                             name = Some(pretty_name);
1124                         }
1125                     }
1126 
1127                     TypeKind::Enum(enum_)
1128                 }
1129                 CXType_Record => {
1130                     let complex = CompInfo::from_ty(
1131                         potential_id,
1132                         ty,
1133                         Some(location),
1134                         ctx,
1135                     )
1136                     .expect("Not a complex type?");
1137 
1138                     if !is_anonymous {
1139                         // The pretty-printed name may contain typedefed name,
1140                         // but may also be "struct (anonymous at .h:1)"
1141                         let pretty_name = ty.spelling();
1142                         if clang::is_valid_identifier(&pretty_name) {
1143                             name = Some(pretty_name);
1144                         }
1145                     }
1146 
1147                     TypeKind::Comp(complex)
1148                 }
1149                 CXType_Vector => {
1150                     let inner = Item::from_ty(
1151                         ty.elem_type().as_ref().unwrap(),
1152                         location,
1153                         None,
1154                         ctx,
1155                     )?;
1156                     TypeKind::Vector(inner, ty.num_elements().unwrap())
1157                 }
1158                 CXType_ConstantArray => {
1159                     let inner = Item::from_ty(
1160                         ty.elem_type().as_ref().unwrap(),
1161                         location,
1162                         None,
1163                         ctx,
1164                     )
1165                     .expect("Not able to resolve array element?");
1166                     TypeKind::Array(inner, ty.num_elements().unwrap())
1167                 }
1168                 CXType_Elaborated => {
1169                     return Self::from_clang_ty(
1170                         potential_id,
1171                         &ty.named(),
1172                         location,
1173                         parent_id,
1174                         ctx,
1175                     );
1176                 }
1177                 CXType_ObjCId => TypeKind::ObjCId,
1178                 CXType_ObjCSel => TypeKind::ObjCSel,
1179                 CXType_ObjCClass | CXType_ObjCInterface => {
1180                     let interface = ObjCInterface::from_ty(&location, ctx)
1181                         .expect("Not a valid objc interface?");
1182                     if !is_anonymous {
1183                         name = Some(interface.rust_name());
1184                     }
1185                     TypeKind::ObjCInterface(interface)
1186                 }
1187                 CXType_Dependent => {
1188                     return Err(ParseError::Continue);
1189                 }
1190                 _ => {
1191                     warn!(
1192                         "unsupported type: kind = {:?}; ty = {:?}; at {:?}",
1193                         ty.kind(),
1194                         ty,
1195                         location
1196                     );
1197                     return Err(ParseError::Continue);
1198                 }
1199             }
1200         };
1201 
1202         name = name.filter(|n| !n.is_empty());
1203 
1204         let is_const = ty.is_const() ||
1205             (ty.kind() == CXType_ConstantArray &&
1206                 ty.elem_type()
1207                     .map_or(false, |element| element.is_const()));
1208 
1209         let ty = Type::new(name, layout, kind, is_const);
1210         // TODO: maybe declaration.canonical()?
1211         Ok(ParseResult::New(ty, Some(cursor.canonical())))
1212     }
1213 }
1214 
1215 impl Trace for Type {
1216     type Extra = Item;
1217 
trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item) where T: Tracer,1218     fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
1219     where
1220         T: Tracer,
1221     {
1222         if self
1223             .name()
1224             .map_or(false, |name| context.is_stdint_type(name))
1225         {
1226             // These types are special-cased in codegen and don't need to be traversed.
1227             return;
1228         }
1229         match *self.kind() {
1230             TypeKind::Pointer(inner) |
1231             TypeKind::Reference(inner) |
1232             TypeKind::Array(inner, _) |
1233             TypeKind::Vector(inner, _) |
1234             TypeKind::BlockPointer(inner) |
1235             TypeKind::Alias(inner) |
1236             TypeKind::ResolvedTypeRef(inner) => {
1237                 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1238             }
1239             TypeKind::TemplateAlias(inner, ref template_params) => {
1240                 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1241                 for param in template_params {
1242                     tracer.visit_kind(
1243                         param.into(),
1244                         EdgeKind::TemplateParameterDefinition,
1245                     );
1246                 }
1247             }
1248             TypeKind::TemplateInstantiation(ref inst) => {
1249                 inst.trace(context, tracer, &());
1250             }
1251             TypeKind::Comp(ref ci) => ci.trace(context, tracer, item),
1252             TypeKind::Function(ref sig) => sig.trace(context, tracer, &()),
1253             TypeKind::Enum(ref en) => {
1254                 if let Some(repr) = en.repr() {
1255                     tracer.visit(repr.into());
1256                 }
1257             }
1258             TypeKind::UnresolvedTypeRef(_, _, Some(id)) => {
1259                 tracer.visit(id);
1260             }
1261 
1262             TypeKind::ObjCInterface(ref interface) => {
1263                 interface.trace(context, tracer, &());
1264             }
1265 
1266             // None of these variants have edges to other items and types.
1267             TypeKind::Opaque |
1268             TypeKind::UnresolvedTypeRef(_, _, None) |
1269             TypeKind::TypeParam |
1270             TypeKind::Void |
1271             TypeKind::NullPtr |
1272             TypeKind::Int(_) |
1273             TypeKind::Float(_) |
1274             TypeKind::Complex(_) |
1275             TypeKind::ObjCId |
1276             TypeKind::ObjCSel => {}
1277         }
1278     }
1279 }
1280