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