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